【问题标题】:Is definition necessary in classes that have pure virtual functions AND regular functions?在具有纯虚函数和常规函数的类中是否需要定义?
【发布时间】:2023-03-31 09:30:01
【问题描述】:

如果你创建了一个类,例如有一个纯虚函数,但有一个或多个非纯虚函数,你可以跳过创建实现文件和类的定义吗?

如果有非虚函数也是一样吗?我猜没有……

【问题讨论】:

  • 我认为只要您不尝试调用它们,您实际上不需要定义任何已声明的成员函数(无论是否为虚拟)。然后链接器会抱怨。你问的是这个吗?
  • 那种。基本上我只是想知道你是否总是可以完全跳过定义抽象类,因为你永远不会实例化一个。
  • 你可以,同样你也完全可以跳过定义非抽象类;)不要忘记你不能实例化抽象类,但你可以有一个指向它的指针。

标签: c++


【解决方案1】:

您始终可以通过内联定义所有成员函数来使类只有标题。这与函数是否为虚拟无关。此外,头文件几乎总是已经包含类定义(除非您使用前向声明)。

澄清术语:

类声明:

class C;

具有一个成员函数的类定义:

class C {
  void f();
};

具有一个内联定义的成员函数的类定义:

class C {
  void f() { ... }
};

这三种风格在不同的情况下都是可能的和有用的。对于类模板,您经常使用第三种样式来允许任意实例化。对于有很多代码的普通类,第二种风格很流行,因为它减少了目标代码的大小和编译时间。

【讨论】:

    【解决方案2】:

    除非您不调用任何成员,否则即使您的类不是抽象的,您也不需要拥有他们的声明。

    这是禁止某些运算符的好方法 - 将它们设为私有且无需声明,以确保该运算符不会与此类一起使用。

    【讨论】:

      【解决方案3】:

      你不应该在基类中为纯虚函数创建定义,但你应该为常规函数创建定义。在基类中定义纯虚方法没有任何意义。

      如果一个类是一个抽象类(即如果它由纯虚函数组成),它必须被继承。我们也不能为抽象类创建对象。

      编辑部分:

      class A{
      public:
          int a;
      
          virtual void vDisplay() = 0; //Should not be defined in base class and must be defined in the derived class
          virtual int vGet(); //non pure Virtual function 
          void vSetA(int x); //non virtual member function must be defined
      };
      class B:public A{
          int b;
      public:
          void vDisplay(); //should be defined in derived class
          int vGet();
          void vSetB(int x,int y);
      };
      int A::vGet(){
          return a;
      }
      void A::vSetA(int x){
          a = x;
      }
      void B::vDisplay(){
          cout<<"a="<<a<<"b="<<b;
      }
      int B::vGet(){
          return a;
      }
      void B::vSetB(int x, int y){
          a = x;
          b = y;
      }
      

      【讨论】:

      • 我很确定,虽然它非常违反约定,但实际上您可以为纯虚拟创建定义。
      • @SirYakalot:按照惯例,不应在基类中定义纯虚函数。
      • 你不能在类体内定义纯虚拟,但你可以做void A::vDisplay() { }。如果你想拥有纯虚拟析构函数,你实际上需要做的事情。
      • @jrok:您可以在类主体外部或内部创建。但是,如果我们排除有关纯虚析构函数的主题,那么在类体外部或内部定义纯虚方法是没有意义的。
      • 有时(非常)定义一个纯虚函数是有意义的,例如,派生类可以从它们的函数实现中调用它。发生这种情况时,您不妨定义一个单独的函数default_Xbase_X 以供派生类调用。但是将其称为X 在此类的直接子级和调用他们的 父级实现的子级之间提供了更多的一致性。当然,有些编码风格绝对不会出现这种情况,例如,如果你从不使用继承进行代码共享。
      猜你喜欢
      • 2011-12-25
      • 2010-09-25
      • 1970-01-01
      • 2015-12-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-01
      相关资源
      最近更新 更多