我有一个包含virtual
方法和强制转换操作符的基类:
class Base {
public:
Base() {}
operator int() const { return getInt(); }
protected:
virtual int getInt() const { return 0; }
}
然后我有两个覆盖虚方法的派生类:
class Derived1 {
public:
Derived1() : Base() {}
protected:
virtual int getInt() const override { return 1; }
}
class Derived2 {
public:
Derived2() : Base() {}
protected:
virtual int getInt() const override { return 2; }
}
然后我有一个辅助功能:
Base helper(const bool flag) {
if (flag)
return Derived1();
else
return Derived2();
}
该辅助函数的用意如下:
int one = helper(true); // I expect "one" to be 1
int two = helper(false); // I expect "two" to be 2
但one
和two
都包含0
。我不知道如何解决这个问题。在Derived
类完全构造之前,是否会调用强制转换运算符?我的环境是VS2013。
建议修复(在我的情况下,在回答后)
我最终将helper
函数转换为class
,将Derived
存储为成员并返回对它们的引用(我认为这实际上是一个更好的设计,因为每个{ {1}}调用[]
未构造/分配):
Derived
旁注
接受的答案表明问题的要点是在引用(如Python)中思考所有事情,这是事实。这个问题是一个更大的系统设计的一部分,它允许在C ++中使用类似Python的语法访问从SQLite数据库返回的结果。链接方括号如:class Helper {
public:
Helper();
const Base& get(const bool flag) const {
if (flag)
return mDerived1;
else
return mDerived2;
}
private:
Derived1 mDerived1;
Derived2 mDerived2;
}
。
答案 0 :(得分:3)
您的helper
函数按值返回Base
,它会删除您在函数内创建的对象的任何派生函数,从而导致虚方法调用基本版本。
答案的要点是你可能习惯于像Python或Java这样的语言,其中一切都是引用(我在使用这些语言时犯了相反的错误)。在C ++中,除非您指定所有内容,否则一切都是按值进行的,并且当按值返回时,切片问题会出现。
您要做的是在堆上分配适当的派生类型,并从helper
函数返回指向该对象的智能指针。智能指针将确保您不会泄漏内存,并通过返回指针而不是按值返回,确保多态在程序中仍然有效。