在超类中调用抽象方法,并在C++中的子类中实现它

Invoke abstract method in super class, and implement it in subclass in C++?

本文关键字:子类 实现 C++ 超类 调用 抽象方法 并在      更新时间:2023-10-16

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

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

SuperClass.java

public abstract class SuperClass {
    public SuperClass() {
        method();
    }
    private void method() {
        unimplementedMethod();
    }
    protected abstract void unimplementedMethod();
}

SubClass.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++中实现这一点,那将是非常棒的。:)

通常,您要查找的是virtual关键字。简而言之,virtual声明了此方法可以被覆盖的意图。注意,这样的方法仍然可以有一个实现——virtual只是使它可以被覆盖。要声明一个"抽象方法",可以说declare intent ofplease provide a implementation in the derived classwith = 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++中,您永远不应该在构造函数中调用虚拟函数,因此它不能像字面上那样工作。最好使用单独的成员功能

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,这样它就可以在整个类层次结构中使用,但虚拟实现函数应该是private,因为它只需要由同一类中的访问器函数看到。简而言之:受保护的非虚拟和私人虚拟。

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

在C++中,这些被称为纯虚拟函数/方法。

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

virtual doSomething() = 0; // pure virtual

在SO周围搜索"c++纯虚拟",你会发现大量的答案。

您需要使用虚拟方法。实现方式如下:

/* 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");
}

您将方法声明为virtual:

代码段:

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"使其虚拟,即:基没有自己的实现,而是依赖于子级的实现。这样的类不能实例化(即:抽象类)。