关于java:覆盖C ++中的规则

Overriding rules in C++

从Java的角度来看,我惊讶地发现,您只能重写具有虚拟关键字的基本方法。在爪哇中,使用最后一个关键字声明无法重写的方法。

我脑子里有个想法,就是你很少想禁止凌驾于世,这样别人就可以根据自己的情况来扩展你的课程。

所以在C++中,如果你觉得某人可能想在某个阶段继承你的班级(也许几年后有人认为这是一个很酷的想法),你会让你的方法都是虚拟的吗?

或者是有一些重要的原因,想要禁止在C++中,我没有意识到这一点?

作为参考,这是我对每种语言所做的实验:

爪哇

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    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++

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
27
28
29
30
31
32
33
34
35
    class Base
    {
    public:
        Base(void);
        ~Base(void);
        virtual void doSomething();
    };

    void Base::doSomething(){
        std::cout <<"I'm doing the base thing
"
<< 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;

    }


达菲莫和艾尔斯正把你带向正确的方向。我只是想对你说的一件事发表评论:

So in C++ if you feel that someone might want to at some stage inherit
from your class (maybe years later someone thinks its a cool idea) do
you make all your methods virtual?

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

虚拟方法带来了非常轻微的性能下降。对于非关键代码路径,性能影响可能可以忽略不计。但是对于经常被调用的类方法,它可以加起来。编译器不能做太多的内联和直接链接。相反,必须在运行时在v-table数组中查找要调用的虚拟方法。

当我的编码团队中有人开始与"稍后可能会有人想要…"进行设计对话时,我的"未来校对"反模式警报就会响起。设计可扩展性是一回事,但"面向未来的特性"应该推迟到那时。

此外,多年后那个认为这是一个很酷的想法的人,让他自己把类方法转换成虚拟的。不管怎么说,到那时你将进入更大的项目。:)


是的,你必须使你所有的方法都是虚拟的。

Java认为默认情况下一切都是公平的游戏,而禁止它需要采取行动。C++和C语言的观点截然相反。


是的,在C++中,一个类方法只能是EDOCX1×0,如果它在基类中被标记为EDCOX1×1。

如果您的类是为继承而创建的,并且您的类方法打算为基和派生提供不同的行为,那么将该方法标记为virtual

良好阅读:

何时将C++中的函数标记为虚拟?


来自于虚函数缺省的语言的程序员往往会惊讶于C++具有逆向选择的默认值,即非虚拟是默认值。但是,请注意,[具体]虚拟函数的契约很难记录和测试,因为实际上涉及两个不同的契约:

  • 所有覆盖函数的契约,即函数在概念上的作用。
  • 具体功能发生作用的契约
  • 只记录其中的一个并不能真正减少它,因为另一半根本不清楚。这也意味着您不能从具体的实现中瞥一眼实际的合同是什么(假设您处于一种不那么不典型的情况下,文档是由源提供的)。


    即使没有virtual也可以重写基类中的方法。

    以这个小程序为例:

    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
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    #include <iostream>

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

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

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

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

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

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

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

    程序输出为:

    1
    2
    3
    4
    5
    6
    A
    A
    B
    B
    A
    B

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