要求派生类定义方法

时间:2017-12-21 18:45:16

标签: c++ c++11 abstract-class

毫无疑问,我忽视了一些基本的东西,但我的实施显然存在缺陷。

我试图要求派生类来实现在基类中调用的方法。

class IClock
{
public:
    virtual void OnTimeExpired() = 0;
}

class Clock : public IClock
{
    ... // ABC not implemented
}

class Application : public Clock
{
    ... // ABC not implemented
}

class DerivedApp : public Application
{
public: 
    virtual void OnTimeExpired() { ... }
}

我很少使用纯ABCs,所以我认为ClockApplication中定义纯虚方法,它需要Application的所有衍生物定义OnTimeExpired()方法。

我发现这将编译和链接(MSVS-2017),如果DerivedApp未实现该方法,Clock对象将调用未定义的方法并崩溃。

  1. 为什么在没有实现纯虚方法的情况下进行编译?

  2. 如何强制派生Application类来实现OnTimeExpired()方法?

  3. 编辑:崩溃是由于无关的错误 - 我道歉。不过我提出的问题仍然适用。

    这里要求的是一个完整的,可构建的,最小的例子:

    IClock.h:

    #pragma once
    
    class IClock
    {
    public:
        virtual void OnClockTime() = 0;
    };
    

    Clock.h:

    #pragma once
    #include "IClock.h"
    
    class Clock : public IClock
    {
    public:
        Clock();
        virtual ~Clock();
        void ClockUpdate();
        virtual void OnClockTime();
    
    private:
        float elapsed_time;
    };
    

    Clock.cpp:

    #include "Clock.h"
    
    Clock::Clock()
        : elapsed_time(0.0f)
    {
    }
    
    Clock::~Clock()
    {
    }
    
    void Clock::ClockUpdate()
    {
        elapsed_time += 0.0000001f; // small ticks for testing
        if (elapsed_time >= 1.0f) {
            OnClockTime();
            elapsed_time -= 1.0f;
        }
    }
    void Clock::OnClockTime()
    {}
    

    ApplicationBase.h

    #pragma once
    #include "Clock.h"
    
    class ApplicationBase : public Clock
    {
    public:
        ApplicationBase();
        virtual ~ApplicationBase();
    
        virtual void Init(){}
        virtual void Run(){}
    
    protected:
        bool app_run;
    };
    

    ApplicationBase.cpp:

    #include "ApplicationBase.h"
    
    ApplicationBase::ApplicationBase()
        : app_run(false)
    {
    }
    
    ApplicationBase::~ApplicationBase()
    {
    }
    

    DerivedApp.h:

    #pragma once
    #include "ApplicationBase.h"
    
    class DerivedApp : public ApplicationBase
    {
    public:
        DerivedApp();
        virtual ~DerivedApp();
    
        virtual void Init() {}
        virtual void Run();
    
        //virtual void OnClockTime();
    };
    

    DerivedApp.cpp:

    #include "DerivedApp.h"
    #include <iostream>
    
    DerivedApp::DerivedApp()
    {
    }
    
    DerivedApp::~DerivedApp()
    {
    }
    
    void DerivedApp::Run()
    {
        app_run = true;
        while (app_run) {
            ClockUpdate();
        }
    }
    
    //void DerivedApp::OnClockTime()
    //{
    //  static int counts(0);
    //  std::cout << "Tick..." << std::endl;
    //  counts++;
    //  if (counts >= 10)
    //      app_run = false;
    //}
    

    的main.cpp

    #include "DerivedApp.h"
    
    class App : public DerivedApp
    {
    public:
        App(){}
        ~App(){}
    };
    
    int wmain(int argc, wchar_t * argv[])
    {
        App *app = new App();
        app->Init();
        app->Run();
        delete app;
    }
    

    感谢那些请求最小工作示例的人,我建立了它并且它完全按照我的希望工作。编译器会抱怨App类中没有ABC的实例化。如果我从DerivedApp :: OnClockTime()中删除注释,它将按照我希望的方式编译和运行。显然我的实际代码并没有像我想的那样遵循这个模型,所以现在我需要重新审视我出错的地方。感谢。

2 个答案:

答案 0 :(得分:3)

C ++中没有强制类覆盖某些方法的关键字。但是,通过使OnTimeExpired()纯虚拟,您可以使IClock成为一个抽象类。从IClock派生的任何未实现OnTimeExpired()的类也将自动成为抽象类,因此不允许您创建这些类的对象。这意味着您的代码是完全合法的,除非您尝试制作这些类的对象

答案 1 :(得分:0)

class AbstractBase {
public:
    virtual void someFunc() = 0; // Purely Virtual
};

class AbstractDerived : public AbstractBase {
public:
    void someOtherFunc();

    // Still abstract because the following is not declared-defined
    // void someFunc() override { ... }
};

class NonAbstractDerivedA : public AbstractBase { // Derived From Base
public:
    void someFunc() override { /* do this class's implementation*/ }
};

class NonAbstractDerivedB : public AbstractDerived { // Derived From AbstractDerived
public: 
    void someFunc() override { /* do this class's implementation*/ }
};

的用途:

#include "above"

int main() {
    AbstractBase base; // compiler error

    AbstractDerived derived; // compiler error

    NonAbstractDerivedA derivedA; // should be okay

    NonAbstractDerivedB derivedB; // should be okay

    return 0;
}