我想使用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'
答案 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
,这会触发编译错误。