【问题标题】:Invoke abstract method in super class, and implement it in subclass in C++?在超类中调用抽象方法,并在 C++ 的子类中实现它?
【发布时间】:2012-03-05 07:48:32
【问题描述】:

在 Java 中,可以编写具有未实现的抽象方法和调用抽象方法的非抽象方法的抽象超类。然后在子类中实现了抽象方法。然后,当您创建子类的实例时,超类使用子类中的实现。我如何在 C++ 中实现这一点?

这就是我的意思,但在 Java 中:

SuperClass.java

public abstract class SuperClass {

    public SuperClass() {
        method();
    }

    private void method() {
        unimplementedMethod();
    }

    protected abstract void unimplementedMethod();
}

子类.java

public class SubClass extends SuperClass {

    public SubClass() {
        super();
    }

    @Override
    protected void unimplementedMethod() {
        System.out.println("print");
    }

    public static void main(String[] args) {
        new SubClass();
    }
}

如果你能告诉我这是如何在 C++ 中完成的,那就太棒了。 :)

【问题讨论】:

标签: c++ class methods implementation abstract


【解决方案1】:

一般来说,您要查找的是virtual 关键字。简而言之,virtual 声明了 此方法可以被覆盖 的意图。请注意,这样的方法仍然可以有一个实现-virtual 只是使其可覆盖。要声明“抽象方法”,您可以用= 0 声明请在派生类中提供实现的意图,如下所示。此类方法在 C++ 中称为纯虚拟

但是,您应该注意一些警告。正如下面评论中所指出的,您是从 SuperClass 构造函数中调用 method() 的。不幸的是,由于对象的构造顺序,这在 C++ 中是不可能的。

在 C++ 中,派生类构造函数在分配其成员或执行构造函数主体之前立即调用它的超类构造函数。因此,首先构造基类的成员,最后构造派生类的成员。从基类调用虚拟方法在 Java 中不会像您期望的那样工作,因为派生类尚未构造,因此虚拟方法尚未重定向到派生实现。希望这是有道理的。

但是,在创建后对 SuperClass 对象调用 method() 将按预期工作:它会调用将输出“print”的虚函数。

class SuperClass {

public:
    SuperClass() {
        // cannot call virtual functions from base constructor.
    }
    virtual ~SuperClass() { } // destructor. as Kerrek mentions,
                               // classes that will be inherited from,
                               // should always have virtual destructors.
                               // This allows the destructors of derived classes
                               // to be called when the base is destroyed.

private:
    void method() {
        unimplementedMethod();
    }

protected:
    virtual void unimplementedMethod() = 0; // makes method pure virtual,
                                            // to be implemented in subclass
}

子类.h

class SubClass : public SuperClass {

public:
    SubClass() : SuperClass() { // how the superclass constructor is called.

    }

    // no need for "override" keyword, if the methd has the same name, it will
    // automatically override that method from the superclass
protected:
    void unimplementedMethod() { 
        std::cout << "print" << std::endl;
    }
}

【讨论】:

  • 不不不——你不能在基础构造函数中调用虚函数!
  • 我刚刚注意到超类正在调用该方法。你是对的,这在 C++ 中不起作用。由于施工顺序,我会在答案中提到这个警告。
  • 另外,纯虚函数也可以有实现。
  • 这也是真的。请参阅stackoverflow.com/questions/2089083/… 以获得良好的解释。
【解决方案2】:

在 C++ 中,你永远不应该在构造函数中调用虚函数,所以它的工作方式并不像字面上那样。最好使用单独的成员函数

class SuperClass
{
public:
    void action() { method(); }   // not in the constructor, please
    virtual ~SuperClass() { }     // always a virtual destructor when polymorphic

protected:
    void method() { unimplementedMethod(); }

private:
    virtual void unimplementedMethod() = 0;
};

class SubClass : public SuperClass
{
private:
    virtual void unimplementedMethod() { std::cout << "print" << std::endl; }

// no need to spell out the next couple of functions, but for your entertainment only
public:
    SubClass() : SuperClass() { }
    virtual ~SubClass() { }
};

现在调用:

int main()
{
    SuperClass * p = new SubClass; // construct first...
    p->action();                   // ... then invoke, after construction is complete

    delete p;                      // thank god for that virtual destructor!
}

基构造函数在派生类构造之前运行,因此不能在基构造函数中调用任何派生函数,尤其是不能调用任何纯虚函数。

请注意,privateprotected 是错误的:非虚拟访问函数应该是 protected,所以它可以在整个类层次结构中使用,但虚拟实现函数应该是 @ 987654326@,因为它只需要被同一个类中的访问器函数看到。简而言之:protected-nonvirtual 和 private-virtuals。

(使用示例有点做作,因为您通常不会在 C++ 中使用 new 或原始指针。)

【讨论】:

    【解决方案3】:

    在 C++ 中,这些称为 pure virtual functions/methods。

    基本上你在方法的末尾加上一个“=0”:

    virtual doSomething() = 0; // pure virtual
    

    在 SO 周围搜索“c++ pure virtual”,您会找到大量答案。

    【讨论】:

      【解决方案4】:

      您需要使用虚拟方法。实现是这样的:

      /* here's MyBaseClass.h */
      class MyBaseClass
      {
      public:
          MyBaseClass(void);
          ~MyBaseClass(void);
      
          void MyMethod();
      
      protected:
          virtual void MyUnimplementedMethod() = 0;
      };
      
      
      /* here's MyIneritedClass.h */
      class MyInheritedClass :
          public MyBaseClass
      {
      public:
          MyInheritedClass(void);
          ~MyInheritedClass(void);
      
      protected:
          virtual void MyUnimplementedMethod();
      };
      
      
      /* here's the implementation of the method in the base class */
      void MyBaseClass::MyMethod()
      {
          MyUnimplementedMethod();
      }
      
      
      /* and here's the implementation of the abstract method in the derived */
      void MyInheritedClass::MyUnimplementedMethod()
      {
          _tprintf(L"Hello, world");
      }
      

      【讨论】:

        【解决方案5】:

        你将方法声明为virtual:

        sn-p:

        class Parent{
        public:
            virtual int methodA() {return methodB();}; // calls the abstract method
            virtual int methodB() = 0; // "=0" means pure virtual, not implemented in the base
        }
        
        class Child : public Parent{
        public:
            virtual int methodB() { /* implementation */}
        }
        

        virtual 表示子级可以覆盖实现,然后父级应该调用覆盖的实现。在 virtual 方法的声明中添加“=0”使其虚拟,即:基础没有自己的实现,并且依赖于子实现。这样的类不能被实例化(即:抽象类)。

        【讨论】:

        • 纯虚函数可以有一个实现,即。 e.一个身体,即使它通常不会。您可能需要它来提供可以从子类调用的默认实现。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-12-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-22
        • 2011-02-25
        相关资源
        最近更新 更多