c ++ static polymorphism / CRTP,其他模板参数访问基类成员

时间:2016-07-13 12:18:17

标签: c++ templates static-polymorphism

我想使用CRTP实现静态多态,并在模板参数中添加其他类型。

提供以下方案,如何直接从Derived类访问Base成员?是否可以不指定Base类的完整类型?

#include <iostream>

template<class Derived, class X>
struct Base
{
    void set_a( int a ) { _a = a; }
    protected:
        int _a;
};

template<class X>
struct Derived: public Base<Derived<X>, X>
{
    int get_a( )
    {
        // return Base<Derived<X>,X>::_a; // This works!
        return _a; // error: use of undeclared identifier '_a'
    }
};

struct foo;

int main()
{
    Derived<foo> test;

    auto base_p = static_cast< Base<Derived<foo>, foo>* >( &test );
    base_p->set_a( 42 );

    int a = test.get_a();
    std::cout << a << std::endl;
}

g ++ 5.3.1 / clang ++ 3.8.0输出:

error: use of undeclared identifier '_a'

2 个答案:

答案 0 :(得分:1)

您可以在班级中添加private void OnEditMemberBtnClicked(object sender, RoutedEventArgs e) { try { var isValidateCertificat = IsValidDate(BirthDateTxt); var isValidateBirth = IsValidDate(CertificateDateTxt); var isValidateAutorisation = IsValidDate(AutorizationDateTxt); var isValidateReglement = IsValidDate(RuleDateTxt); if (isValidateBirth && isValidateCertificat && isValidateAutorisation && isValidateReglement) { States.EnumToText(States.StatesEnum.Updating); var typePaiement = BankCheckRadio.IsChecked.Value; var typePaiementText = typePaiement ? "Chèque" : "Espèce"; var doctor = ""; var dateCertificate = ""; if (BankCheckRadio.IsChecked.Value) { doctor = DoctorTxt.Text; dateCertificate = CertificateDateTxt.Text; } var editedMember = new Member { id_Member = _idForEdit, name_Member = UppercaseChar(NameTxt.Text), surname_Member = UppercaseChar(SurnameTxt.Text), birthDate_Member = BirthDateTxt.Text, autorizationDate_Member = AutorizationDateTxt.Text, address_Member = UppercaseChar(AddressTxt.Text), postalCode_Member = PostalCodeTxt.Text, country_Member = UppercaseChar(CountryTxt.Text), fixPhone_Member = FixPhoneTxt.Text, mobilePhone_Member = MobilePhoneTxt.Text, mail_Member = MailTxt.Text, beginDate_Member = BeginDateCombo.Text, ruleDate_Member = RuleDateTxt.Text, subscription_Member = SubscriptionCombo.Text, typePaiement_Member = typePaiement, typePaiementText_Member = typePaiementText, federationNumero_Member = FederationNumeroTxt.Text.ToUpper(), level_Member = LevelCombo.Text, certificate_Member = CertificateCheckbox.IsChecked.Value, doctor_Member = UppercaseChar(doctor), certificateDate_Member = dateCertificate, problem_Member = UppercaseChar(ProblemTxt.Text, true), emergencyName_Member = UppercaseChar(EmergencyNameTxt.Text), emergencyPhone_Member = EmergencyPhoneTxt.Text, BankCheck = _bankChecks }; if (_bankChecks != null) { using (var context = new KravMagaEntities()) { foreach (var bankCheck in _bankChecks) { bankCheck.idMember_BankCheck = editedMember.id_Member; context.Entry(bankCheck).State = EntityState.Added; } context.SaveChanges(); } } new Task(() => EditMember(editedMember)).Start(); } } catch (Exception exception) { States.EnumToText(States.StatesEnum.Error, exception); } } 声明:

using

你仍然需要指定一次。

答案 1 :(得分:0)

Derived范围内,_a未声明但已继承,因此您必须编写this->_a以查找基类或显式写入Base<Derived<X>, X>::_a。后者可以用

导入
using Base<Derived<X>, X>::_a;

Derived的定义中。

<强> TL;博士

如果写了this->_a,则this会自动转发到Base<Derived<X>, X>*以匹配内在operator->

如果仅写入_a,则执行unqualified name lookup。非限定名称查找是基于范围的,与继承无关。在您的示例中,_a位于Derived::get_a,因此在{/ 1>中搜索_a

  • Derived::get_a
  • Derived
  • (文件范围)

找不到_a,这会触发编译错误。