C++ 如何调用精确的派生类方法?
继续我先前的问题: 我有一个验证器类和它的派生类;当我努力的时候 若要返回指向派生类的指针,则方法返回base 类验证器,而不是派生的 我将我的类修改为下一个:C++ 如何调用精确的派生类方法?,c++,polymorphism,C++,Polymorphism,继续我先前的问题: 我有一个验证器类和它的派生类;当我努力的时候 若要返回指向派生类的指针,则方法返回base 类验证器,而不是派生的 我将我的类修改为下一个: class Validator { public: std::string m_name = "BaseValidator"; static const std::map<std::string, Validator *> validators(); void validateModel(Mod
class Validator
{
public:
std::string m_name = "BaseValidator";
static const std::map<std::string, Validator *> validators();
void validateModel(Model &model, const std::vector<std::string> &attrNames);
static Validator *getByName(std::string &name);
virtual void validateAttribute(Model &model, const std::string &attribute);
virtual ~Validator();
virtual std::string name() const;
};
const std::map<std::string, Validator*> Validator::validators()
{
std::map<std::string, Validator*> result;
result["required"] = new RequiredValidator();
return result;
}
void Validator::validateModel(Model &model, const std::vector<std::string> &attrNames)
{
validateAttribute(model, name.at(0));
}
Validator* Validator::getByName(std::string &name)
{
auto g_validators = Validator::validators();
auto validator = g_validators.find(name);
if(validator != g_validators.end()){
return validator->second;
}else{
std::cerr << "Unknow type of validator: " << name << std::endl;
}
return nullptr;
}
void Validator::validateAttribute(Model &model, const std::string &attribute)
{
(void)model;
(void)attribute;
std::cout << this->name() << std::endl;
}
//------------------
class RequiredValidator : public Validator
{
public:
std::string m_name = "RequiredValidator";
void validateAttribute(Model &model, std::string &attribute);
~RequiredValidator();
std::string name() const;
};
std::string RequiredValidator::name() const
{
return m_name;
}
void RequiredValidator::validateAttribute(Model &model, std::string &attribute)
{
(void) model;
(void) attribute;
std::cout << "RequiredValidator!!!" << std::endl;
}
RequiredValidator::~RequiredValidator()
{
}
//------------------
auto validator = Validator::getByName("required");
validator->name();// will output RequiredValidator
//next i'm calling
validator->validateModel(); // whos calling validateAttribute() inside
//and it's output Validator::validateAttribute() //but i wan't
//RequiredValidator::validateAttribute();
//where i was wrong with logic???
与我希望的虚拟方法名称相同,但是
validateAttribute仅从基类调用
仔细查看如何定义void RequiredValidator::validateAttribute 您可能会注意到签名与基本std::string稍有不同&属性不是常量 有一个关键字覆盖可以帮助编译器捕获这些类型的输入错误 首先,正如其他人所指出的, §13.1标准中讨论了不能 过载状态- 仅在存在或不存在 常量和/或volatile是等效的。也就是说,常量和volatile 忽略每个参数类型的类型说明符[…] 仅位于最外层的const和volatile类型说明符 以这种方式忽略参数类型规范;常数 和隐藏在参数类型中的易失性类型说明符 规范是重要的,可用于区分 重载函数声明。[……] 确定要声明、定义或调用哪个函数时。 特别是,对于任何类型的T,“指向T的指针”,“指向常量T的指针,” 和“指向volatile T的指针”被视为不同的参数类型, “引用T”、“引用常数T”和“引用 挥发性T.“ 所以,
void validateAttribute(Model &model, std::string &attribute) override;
不一样
void validateAttribute(Model &model, const std::string &attribute);
其次,如果您使用C++11或更高版本,并在函数声明中使用override关键字,则可以避免遇到此类错误,如下所示。
使用override关键字,除非派生类中的函数签名与基类中的函数签名匹配,否则此代码将不允许编译
class RequiredValidator : public Validator
{
public:
std::string m_name = "RequiredValidator";
void validateAttribute(Model &model, std::string &attribute) override;
~RequiredValidator();
std::string name() const;
};
编辑:p.s.覆盖需要虚拟关键字。因此,
virtual void validateAttribute(Model &model, std::string &attribute) override;
删除所有不相关的代码让我们看看基类和继承类的签名:
class Validator {
public:
virtual void validateAttribute(Model &model, const std::string &attribute);
};
class RequiredValidator : public Validator {
public:
void validateAttribute(Model &model, std::string &attribute);
};
在基类的::validateAttribute中,您为其参数Model&Model和const std::string&attribute提供了属性,在派生类的::validateAttribute中,您为其参数Model&Model和std::string&attribute提供了属性
这里的冲突是const std::string&和std::string&。请事先使这两个函数完全匹配,或者在您的情况下,由于您试图使用多态性,您可以在派生类中通过执行以下操作来解决此问题:
/*virtual*/ void validateAttribute( Model& model, std::string& string ) override;
这里的override关键字将生成一个编译器错误,用于解释问题所在。如果您计划从这个派生类继承,请不要忘记添加virtual。是否需要重新定义virtual关键字?因为错误:标记为“override”的非虚拟成员函数隐藏虚拟成员函数validateAttribute签名在基和派生类中必须相同只有一件事:对“Validator::name[abi:cxx11]const”的未定义引用。如何修复?@exru:表示缺少虚拟std::string name const;的实现;。谢谢兄弟,我自己修好的。它说的是:1.听编译器说。教英语3。阅读docas e.t.c.所有用我糟糕的英语拍摄的麻烦事。但我正在努力,我花了很多时间在PHP上。我在C++上写了2个月的感谢。@ EXRU,实际上,如果有一个const但不是一个引用,那么它就可以超载了,即ValueRealEntAdvestODel&模型,STD::String属性和ValueValueAtestMeToDel&模型,const STD::String and Atple不会有这个问题。当然,这不是我们想要做的。。我只是想详细说明一点。区别在于引用和指针!对他们来说,康斯特起了作用。谢谢兄弟。我修好了@Joey Mallone您是指评论第二个签名中的const std::string属性吗?因为T和const T在签名中是相同的,但是T和const T&肯定不是…@MaxLanghof,是的。但我现在无法编辑评论:我的意思是,void validateAttributeModel&model、std::string属性和void validateAttributeModel&model、const std::string属性可以重载。在两个声明中都没有(&N)。