我目前在使用在基类中定义为const的函数时遇到问题。
我正在使用上面的虚函数实现派生类,但是使用非const返回值。我想在不更改基类的情况下实现它,因为还有其他使用此虚函数的外部类。不更改此虚函数的原因是存在使用相同函数的其他派生类。
任何帮助非常感谢。
例如:
我正在实现一个具有不同返回值的派生类函数double DerivedClass1::Function()
,它是double BaseClass::Function() const
中定义的虚函数。我无法控制的double DerivedClass2::function() const
和double DerivedClass3::Function() const
使用相同的功能。如果没有对基类进行任何或最小的更改,我该怎么做。
答案 0 :(得分:1)
我不确定我是否完全理解你,但也许这就是你想要的:
struct BaseClass {
virtual double Function() {return const_cast<const BaseClass*>(this)->Function();}
virtual double Function() const=0;
virtual BaseClass() {}
};
struct DerivedClass1: public BaseClass {
virtual double Function() {stuff};
virtual double Function() const {throw std::logic_error("UNIMPLEMENTED");};
};
struct DerivedClass2: public BaseClass {
virtual double Function() const {stuff};
};
毋庸置疑,这是一个非常糟糕的主意。 BaseClass实现将可变实例重定向到现有的const
函数,除非它们已被派生类覆盖,正如您在DerivedClass1
中所做的那样。问题是如果您在Function()
上调用const DerivedClass1
,则会在运行时收到异常。
答案 1 :(得分:1)
你有:
struct Base {
virtual double Function() const;
};
struct Derived1 : Base {
virtual double Function() const;
};
struct Derived2 : Base {
virtual double Function() const;
};
你想:
struct Derived1 : Base {
virtual double Function(); // overrides virtual function in base
};
所以,首先你需要向Base
添加一个非const虚函数,否则你不会覆盖任何东西。问题是,基类功能应该定义为什么?对于最小的中断,它应该做同样的事情,通过非const引用当前调用函数 - 调用const函数:
struct Base {
virtual double Function() const;
virtual double Function() { return static_cast<const Base*>(this)->Function(); }
};
struct Derived1 : Base {
virtual double Function() const;
virtual double Function();
};
struct Derived2 : Base {
virtual double Function() const;
// no need to override non-const Function
};
我认为这仍然可能会破坏现有代码,例如,如果您接受指向函数的const和非const版本的指针,那么之前它们会比较相等而现在它们不会:
typedef double (Base::*constfunc)() const;
typedef double (Base::*mutfunc)();
((mutfunc)(constfunc(&Base::Function)) == (mutfunc(&Base::Function))); // was true, now false
对于Base
类的典型用户,添加新功能可能是无害的。
但是,你说:“使用上面的虚函数,但是使用非const返回值”,你的示例函数已经有一个非const返回值(double
),即使是函数的const版本。因此,答案无法解决这个问题,并且通过隐藏您的真实用例,您可能会得到比您更好地反映实际代码的示例更糟糕的答案。
答案 2 :(得分:0)
想要覆盖虚拟基本方法的派生方法必须使用与基本方法完全相同的签名,包括const
的使用,否则派生方法只会隐藏基本方法而不是覆盖它。如果要覆盖,则无法更改派生类中的签名。