覆盖C ++中的规则

时间:2012-01-03 10:23:40

标签: java c++ override

从Java的角度来看,我很惊讶地发现你只能覆盖拥有virtual关键字的基本方法。 在Java中,您使用final关键字来声明无法覆盖方法。

我的想法是,我很少想要禁止覆盖,以便有人可以按照他们认为合适的方式扩展课程。

所以在C ++中,如果你觉得有人可能想在某个阶段继承你的课程(也许多年后有人认为这是一个很酷的主意),你是否将所有方法都虚拟化了?

或者是否有一些关键的原因想要在C ++中禁止这个我不知道的?

for Reference这是我用各种语言进行的实验:

爪哇     

    public class Base {

    void doSomething(){
    System.out.println("Doing the base thing");
    }
    }
    public class Derived extends Base {

    void doSomething(){
    System.out.println("Doing the derived thing");
    }

    public static void main(String... argv){
        Base object = new Derived();
        object.doSomething();
    }
    }

C ++

    class Base
    {
    public:
        Base(void);
        ~Base(void);
        virtual void doSomething();
    };

    void Base::doSomething(){
        std::cout << "I'm doing the base thing\n" << std::endl;
    }

    class Derived :
        public Base
    {
    public:
        Derived(void);
        ~Derived(void);
        void doSomething();
    };

    void Derived::doSomething(){
        std::cout << "I'm doing the dervied thing" << std::endl;
    }


    int main(void){

        Base * object = new Derived;

        object->doSomething();
        return 0;

    }

4 个答案:

答案 0 :(得分:1)

是的,在C ++中,如果在Base类中标记为overidden,则类方法只能为virtual

如果您的类是为了继承而您的类方法是为Base提供不同的行为并派生,那么将该方法标记为virtual

好读:

<强> When to mark a function in C++ as a virtual?

答案 1 :(得分:1)

是的,您必须将所有方法都设为虚拟。

Java采取的立场是,默认情况下,所有内容都是公平的游戏,禁止它需要采取行动。 C ++和C#采取相反的观点。

答案 2 :(得分:1)

duffymo和Als正朝着正确的方向前进。我只是想对你说的一件事发表评论:

  

所以在C ++中如果你觉得有人可能想要在某个阶段继承   从你的班级(也许多年后有人认为这是一个很酷的主意)做   你把所有方法都虚拟了吗?

从软件工程的角度来看:如果您没有立即使用继承并且没有使用接口,那么我不建议将您的方法声明为虚拟。

虚拟方法伴随着轻微的性能下降。对于非关键代码路径,性能影响可能微不足道。但是对于被大量调用的类方法,它可以加起来。编译器无法进行内联和直接链接。相反,必须在运行时在v表数组中查找要调用的虚方法。

当我的编码团队中的某个人开始与“有人可能会在某个时候想要......”的设计对话时,那时我的“未来校对”反模式警报响起。设计可扩展性是一回事,但“未来的特征”应该推迟到那时为止。

除此之外 - 这个家伙多年后认为这是一个很酷的主意 - 让他成为拥有将课程方法变为虚拟的人。无论如何,你将在那时进入更大的项目。 :)

答案 3 :(得分:0)

即使没有virtual,您也可以覆盖基类中的方法。

以这个小程序为例:

#include <iostream>

struct A
{
    void m()
        { std::cout << "A\n"; }

    virtual void n()
        { std::cout << "A\n"; }
};

struct B : public A
{
    void m()
        { std::cout << "B\n"; }

    virtual void n()
        { std::cout << "B\n"; }
};

int main()
{
    A a;
    a.m();
    a.n();

    B b;
    b.m();
    b.n();

    A &c = b;
    c.m();
    c.n();
}

该计划的输出是:

A
A
B
B
A
B

如您所见,方法B::m会覆盖A中的相同方法。但这仅在使用B的确切实例时才有效。在第三种情况下,当使用对基类的引用时,您需要virtual才能使其工作。