override c++ virtual method
我有一个类模板,其中一些方法被定义为虚拟的,以使类的用户能够在派生类中为它们提供实现。请注意,在我的模板类中,有一些使用虚拟方法的非虚拟方法(应该返回值的虚拟类在非虚拟类中调用)。
您能给我一个正确代码的简单例子吗?父类的虚方法应该返回一个值(但它的实现是在子类中提供的),父类中虚方法返回的值在该类的其他方法中使用。因为我看到了某处(例如这里:安全地覆盖C++虚拟函数),这会导致一些问题,并且用户定义的方法将注意重写父类的虚拟方法。
注意:我使用g++编译器用code::blocks编程。
编辑:根据这里的要求,我想要的一个简单示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 | template<typename T> class parent { public: // Public methods that user can call int getSomething(T t); void putSomething(T t, int x); // public method that user should implement in his code virtual float compute(T t) { } // protected or private methods and attributes used internally by putSomething ... float doComplexeThings(...); // this can call }; |
方法compute()应由用户(子类)实现。但是,这个方法compute()是由putshing()和docomplexthings()调用的。
如果可以在编译器中使用C++ 11特性,那么可以用EDCOX1×0的特殊标识符将重写标记为:
1 | float compute() override; |
派生类中的上述行将导致编译器错误,因为函数不会重写基中的成员函数(签名不正确,缺少参数)。但请注意,这必须在每个派生类中完成,这不是可以从基类强制实施的解决方案。
从基类中,只能通过使函数纯虚拟来强制重写,但这会改变语义。它不会在覆盖时避免问题,而是在所有情况下强制覆盖。我将避免使用这种方法,如果您要遵循它,并且有一个对基类型的合理实现,请将函数设置为虚拟的,并提供一个定义,以便派生类的实现可以只调用基类型的函数(即强制实现,但在最简单的情况下,它只会将调用转发到亲本)
您只需确保方法具有相同的签名(包括const/mutable修饰符和参数类型)。如果未能重写子类中的函数,可以使用纯虚拟定义来引发编译器错误。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | class parent { public: // pure virtual method must be provided in subclass virtual void handle_event(int something) = 0; }; class child : public parent { public: virtual void handle_event(int something) { // new exciting code } }; class incomplete_child : public parent { public: virtual void handle_event(int something) const { // does not override the pure virtual method } }; int main() { parent *p = new child(); p->handle_event(1); // will call child::handle_event parent *p = new incomplete_child(); // will not compile because handle_event // was not correctly overridden } |
这个问题是在2013年提出的。它很旧,但我发现了一些新的东西,这些东西在答案中不存在。
我们需要理解三个概念:过载、覆盖和隐藏。
简而言之,您希望从基类重载继承函数。但是,重载是一种为函数添加多个行为的机制,它需要在相同的尺度下使用所有这些函数。但虚拟函数显然在基类中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | class A { public: virtual void print() { cout << id_ << std::endl; } private: string id_ ="A"; }; class B : A { public: using A::print; void print(string id) { std::cout << id << std::endl; } }; int main(int argc, char const *argv[]) { /* code */ A a; a.print(); B b; b.print(); b.print("B"); return 0; } |
Add using A::print; in your derive class will do the work!
尽管我觉得这不是一个好主意,因为过载和继承背后的哲学是不同的,把它们套在一起可能不是一个好主意。