【问题标题】:Interface with non-copyable features具有不可复制功能的接口
【发布时间】:2011-08-12 18:40:38
【问题描述】:

我正在尝试实现一个日志工厂,并且我使用了一个接口,以便我可以随时交换记录器。

界面如下

class ILogger
{
public:

    //Only allow string input. The entire ARC is going to be non-unicode.
    virtual void log(std::string message, eLogLevel level=DEBUG) = 0;

protected:
    virtual ~ILogger(void){};


private:
    // No one can create an ILogger as it is abstract but should also
    // disallow copying... why copy a logger? Only one per file. Besides want to 
    // force people to use the factory.
    /*ILogger(const ILogger&);
    ILogger& operator=(const ILogger&);*/ // REMOVED THIS BECAUSE OF ERROR

};

这是一个派生类(头文件)

class GenericLoggerImpl :
    public ILogger
{
public:
    virtual ~GenericLoggerImpl(void);
    virtual void log(std::string message, eLogLevel level=DEBUG);

private:
    GenericLoggerImpl(void); //USE THE FACTORY
    std::tr1::shared_ptr<GenericLogger> pImpl; //This is the implementation
    friend class LoggerFactory; // class LoggerFactory can now build these
};

CPP

GenericLoggerImpl::GenericLoggerImpl(void):pImpl()
{
    pImpl = std::tr1::shared_ptr<GenericLogger> (new GenericLogger()); //This is the implementation
}

GenericLoggerImpl::~GenericLoggerImpl(void)
{
}

void GenericLoggerImpl::log(std::string message, eLogLevel level)
{
    pImpl->logMsg(message.c_str(),level);
}

现在问题来了。看到在ILogger界面中,我注释掉了一段私有代码吗?那是为了阻止任何人复制 ILogger 派生类(如 boost::noncopyable 所做的)。这很有意义(无论如何对我来说),因为它不允许单独的记录器实例访问同一个文件,并让用户通过我方便的 LoggerFactory。

当包含这些行时,我会收到以下错误:

genericloggerimpl.cpp(6) : 错误 C2512: 'ILogger' : 没有合适的默认构造函数可用

那是关于什么的?我不希望这些对象是可复制的。我该怎么做?

【问题讨论】:

  • 重新编译之前保存了吗?而且我不明白在您的代码中实际调用构造ILogger(子)对象的部分是什么? GenericLogger 的类是什么样的?
  • @Mahesh - 我有一个单独的 LoggerFactory 对象,它提供了许多创建者功能。可以看到它是实现类GenericLoggerImpl的朋友。 GenericLogger 是一个日志类,比较复杂。您可以将 GenericLoggerImpl 视为该类的适配器。或者换句话说,GenericLoggerImpl 是一个 ILogger,以 GenericLogger 的形式实现。

标签: c++ visual-c++ interface


【解决方案1】:

any 用户定义的构造函数(包括复制构造函数)的存在将阻止编译器生成默认构造函数。您的子类 GenericLogger 依赖于 ILogger 的默认构造函数的存在(它被隐式调用,因为在 GenericLogger 的构造函数的初始化列表中没有另行指定),因此出现错误。

要解决此问题,只需为 ILogger 声明一个受保护的普通默认构造函数:

ILogger() {}

【讨论】:

  • 谢谢,这很好用。最简单的修复总是最好的:)
  • @Dennis:另一个提示:如果你可以访问 Boost,你可以使用boost::noncopyable 来表示一个对象是不可复制的。它更明确一些,因此更简洁。
  • 好点。我必须检查项目存储库以查看 noncopyable 是否已经存在。
【解决方案2】:

您可以从以下类继承来禁止复制您想要保护的任何类:

class no_copy
{
protected:
    // For derived class. Protected just to avoid direct instantiation of this class
    no_copy(){}

private:    
    no_copy(const no_copy&);
    void operator =(const no_copy&);
};

例子:

class MyClass:public no_copy
{
};

错误:

MyClass cls1;
MyClass cls2(cls1); // Error
cls2 = cls1; // Error

【讨论】:

    猜你喜欢
    • 2021-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多