【问题标题】:pure virtual function and abstract class纯虚函数和抽象类
【发布时间】:2010-07-06 11:58:27
【问题描述】:

我有以下类,Base 和 Derived,当我编译时编译器抱怨它无法创建 DLog 的实例,因为它是抽象的。

谁能告诉我如何解决这个错误?

我猜是因为不是两个纯虚函数都没有在派生中实现。

class Logger
{
public:

    virtual void log(int debugLevel, char* fmt, ...) = 0;
    virtual void log(string logText, int debugLevel, string threadName = "") = 0;

    static Logger* defaultLogger() {return m_defaultLogger;}
    static void setDefaultLogger(Logger& logger) {m_defaultLogger = &logger;}

protected:

    static Logger* m_defaultLogger;
};

class DLog : public Logger
{
public:
    DLog();
    ~DLog();

    static DLog *Instance();
    static void Destroy();

    void SetLogFilename(std::string filename);
    void SetOutputDebug(bool enable);
    std::string getKeyTypeName(long lKeyType);
    std::string getScopeTypeName(long lScopeType);
    std::string getMethodName(long lMethod);

    virtual void log(string logText, int debugLevel)
    {
        Log(const_cast<char*>(logText.c_str()));
    }

    void Log(char* fmt, ...);

private:

    static DLog *m_instance;

    std::string m_filename;
    bool m_bOutputDebug;
};

// DLog 实例化为单例

DLog *DLog::Instance()
{
    if (!m_instance)
        m_instance = new DLog();
    return m_instance;
}

【问题讨论】:

  • 显然,您需要在派生类中实现 PVF。
  • 拜托拜托,不要用省略号重载函数。将为您节省数小时的头发拉扯和深夜调试。
  • @Alex:不是超载......它的大写 L 是 Log 函数。其他都是小写...
  • 但是log 方法有两个重载,一个带有省略号。请改用 Boost.Format 或类似技术。

标签: c++ abstract-class pure-virtual


【解决方案1】:
virtual void log(string logText, int debugLevel, string threadName = "") = 0;

尚未在 DLog 类中实现。您必须实现它,因为它在基类中是纯虚拟的。

您可能在DLog 中的log 的第一次重载中就是这个意思:

virtual void log(string logText, int debugLevel, string /*threadname*/)
{
    Log(const_cast<char*>(logText.c_str()));
}

编辑:你也没有实现

的重载
virtual void log(int debugLevel, char* fmt, ...) = 0;

请注意,尽管使用 const_cast 是一个非常糟糕的主意,并且是未定义的行为。您可以通过执行以下操作来获得明确定义的行为:

virtual void log(string logText, int debugLevel, string /*threadname*/)
{
    logText.push_back('\0'); // Add null terminator
    Log(&logText[0]); // Send non-const string to function
    logText.pop_back(); // Remove null terminator
}

不过更好的是,首先让“Log” const 正确。

【讨论】:

  • 我认为字符串是空终止的??或者它只是一个以 null 结尾的 char*?
  • @Tony:一些std::string 实现将有一个空终止符,但它们不需要有一个,除非您调用c_str 成员。但是,您不能修改由c_str 返回的缓冲区并且具有明确定义的行为。
【解决方案2】:

通过从Logger 派生您的DLog 类,您确保将为基类中声明的所有纯虚方法(假设您不希望DLog 作为抽象类)提供实现。在这里,您没有为纯虚函数提供实现,因此类DLog 成为一个抽象类。在 C++ 中,您无法创建抽象类的实例,因此会出现编译器错误。顺便说一句,您的基类缺少虚拟析构函数。

【讨论】:

    猜你喜欢
    • 2013-01-15
    • 2020-07-01
    • 1970-01-01
    • 2019-04-20
    • 1970-01-01
    • 2013-06-29
    • 2011-03-21
    • 2019-12-08
    • 1970-01-01
    相关资源
    最近更新 更多