在继续我之前的问题: How to return derived type?
我有一个Validator类和从中派生的类;当我尝试 返回指向派生类的指针,然后方法返回基数 class(Validator)而不是Derived。
我将我的课程修改为下一个:
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???
相同的虚拟方法name()如我所愿,但是 仅从基类调用validateAttribute()。
答案 0 :(得分:3)
仔细查看您如何定义void RequiredValidator::validateAttribute()
您可能会注意到签名与基本签名略有不同(std::string &attribute
不是const
)
有一个关键字override
,可以帮助编译器捕获这些类型的错字。
答案 1 :(得分:2)
§13.1,其中标准讨论了不能为 重载状态-
仅在是否存在 const和/或volatile是等效的。也就是说,const和volatile 每个参数类型的类型说明符都会被忽略[...]
仅在最外层的const和volatile类型说明符 以这种方式忽略参数类型规范; const 以及隐藏在参数类型中的易失类型说明符 规格很重要,可以用来区分 重载的函数声明。 [...]
在确定要声明,定义或调用的函数时。 “尤其是对于任何类型T,“指向T的指针”,“指向const T的指针” 和“易失性T的指针”被认为是不同的参数类型, 就像“引用T”,“引用const 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. override
需要virtual
关键字。因此,
virtual void validateAttribute(Model &model, std::string &attribute) override;
答案 2 :(得分:2)
删除所有不相关的代码,让我们看一下基类和继承类的签名:
var getRowMetadata = function(old_metadata_provider) {
return function (row) {
var item = this.getItem(row),
ret = old_metadata_provider(row);
//Handle group rows
if (item.__group) {
//adding a class
ret.cssClasses += ' ' + (item.collapsed === 1 ? 'collapsed' : 'expanded');
//or trigger a custom event....
}
//"Normal rows"
else if (item) {
ret = ret || {};
...
}
return ret;
};
};
....
dataview = new Slick.Data.DataView({
groupItemMetadataProvider: groupItemMetadataProvider,
inlineFilters: true
});
dataview.getItemMetadata = getRowMetadata(dataview.getItemMetadata);
在基类的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
。