Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 什么时候开始;虚拟的;派生类中实际需要的属性?_C++_Virtual - Fatal编程技术网

C++ 什么时候开始;虚拟的;派生类中实际需要的属性?

C++ 什么时候开始;虚拟的;派生类中实际需要的属性?,c++,virtual,C++,Virtual,我试图理解,为了使给定类的任何后代能够启用多态行为,应该在何时/何地编写“virtual”关键字,因为我在别处找不到关于这个问题的具体信息 就我所尝试的,在基类中的函数上使用virtual会自动使该函数对于任何子体都是虚拟的。然而,互联网上的许多代码片段经常在子体中再次声明这些函数为虚拟函数 struct A { virtual void foo1() { std::cout << "[A] foo1.\n"; } virtual void foo2() { std:

我试图理解,为了使给定类的任何后代能够启用多态行为,应该在何时/何地编写“virtual”关键字,因为我在别处找不到关于这个问题的具体信息

就我所尝试的,在基类中的函数上使用virtual会自动使该函数对于任何子体都是虚拟的。然而,互联网上的许多代码片段经常在子体中再次声明这些函数为虚拟函数

struct A {
    virtual void foo1() { std::cout << "[A] foo1.\n"; }
    virtual void foo2() { std::cout << "[A] foo2.\n"; }
};
struct B : public A {
    virtual void foo1() { std::cout << "[B] foo1.\n"; }
            void foo2() { std::cout << "[B] foo2.\n"; }
};
结构A{
virtual void foo1(){std::cout
对于我所尝试的,在基类中的函数上使用virtual会自动使该函数对于任何子体都是虚拟的。

这是真的,子方法自动继承父方法的
virtual
ness


人们在子类中将
virtual
重申为一种约定,只是为了明确表示子类打算重写一个虚拟方法(不过在C++11中我们有
override
).

除非您打算对其进行派生,否则没有特别的理由说明子类在成员上应该有virtual关键字。

是否使类成员成为虚拟成员的决定仅取决于您打算如何派生类。如果您不打算派生类,则

一个更完整的解释,考虑下面的代码。如果我现在打算派生B,或者使B成为一个可重用的代码块,我可能会通过阻塞对A成员的访问来破坏代码。

   #include <iostream>

class A
{
public:
  virtual void foo1()
  {
    std::cout<<"A.foo1"<<std::endl;
  }
  void foo2()
  {
    std::cout<<"A.foo2"<<std::endl;
  }
};

class B : public A
{
public:
  void foo1()
  {
    std::cout<<"B.foo1"<<std::endl;
  }
  void foo2()
  {
    std::cout<<"B.foo2"<<std::endl;
  }
};


int main()
{
  A* a = new A();
  a->foo1();
  a->foo2();
  B* b = new B();
  b->foo1();
  b->foo2();
  delete a;
  a=b;
  a->foo1();
  a->foo2();
}

注意事项:

  • 声明为虚拟的任何方法都是动态绑定的(运行时)。 任何其他方法都是静态绑定的(编译时)

  • 任何方法一旦声明为虚拟,无论在下面的类中是否声明为虚拟,在下面的所有继承级别上都保持虚拟。例如,假设层次结构是:Man->Indian->Tamilian

  • 如果do_work()是一个虚拟方法,那么即使对Tamilian来说它仍然是虚拟的,即使它仅在Man中声明为虚拟的

    虚拟关键字是如何工作的?

    将do_work()声明为virtual仅仅意味着:要调用的do_work()将仅在运行时确定

    如果我有

    Man *man;
    man = new Indian();
    man->do_work(); // Indian's do work is only called.
    
    如果未使用virtual,编译器将根据调用的对象静态确定或静态绑定virtual。因此,如果Man的对象调用do_work(),Man的do_work()将被调用,即使它指向印度对象


    令我惊讶的是,我发现纯虚函数也可以有体!我认为它们不能。但是,事实是它们可以。这意味着可以调用抽象类的纯虚函数!!!两位非常优秀的作者是Bjarne Stroustrup和Stan Lippman…因为他们编写了这种语言。

    派生类中的虚函数是只是信息记住C++11 override关键字。它修复了许多由这种行为引起的讨厌的维护错误。C++11的最佳实践是什么?在子类中同时使用virtual和override,还是只使用override?只需使用
    override
    。编译器会告诉您是否出错;-)您在此处显示的行为是由prese引起的A函数上不存在或不存在
    virtual
    。是否在B函数上指定virtual将不会有任何区别。
    Man *man;
    man = new Indian();
    man->do_work(); // Indian's do work is only called.