在没有朋友的情况下提供对基类的受保护

时间:2014-11-30 07:47:29

标签: c++ inheritance

我将从解释我的情况开始。

我有一个自动实现引用计数类型的基类。它允许我将C风格的init()free()库调用包装到引用计数的API中。

template<typename T>
class Service {
public:
    Service() {
        if(s_count++ == 0) {
            T::initialize();
        }
    }

    ~Service() {
        if(--s_count == 0) {
            T::terminate();
        }
    }

private:
    static int s_count;
};

template<typename T>
int Service<T>::s_count = 0;

希望实现这些初始值设定项和终结符的类将从Service派生,如下所示:

class Test : public Service<Test> {
    friend class Service<Test>;

private:
    static void initialize() {
        std::cout << "Initialized" << std::endl;
    }

    static void terminate() {
        std::cout << "Terminated" << std::endl;
    }
};

然而,声明很混乱,因为我必须从我的Service类继承并与他们交往。 有没有办法允许基类自动访问派生类的受保护或私有成员?如果没有,我也可以问一下是否有更好的方式来编写我的&# 39;已经完成了。

3 个答案:

答案 0 :(得分:1)

&#34;有没有办法允许基类自动访问派生类的受保护或私有成员?&#34;

基类无法正式访问派生类的私有/受保护成员。一般来说,基类的设计方式使得他们不需要知道派生类的任何内容。因此,如果需要从基类访问派生类中的成员,那么您应该重新考虑您的设计。

编辑(根据@RSahu的拟议文章): -

尽管在某些情况下从基类访问派生类的成员函数可能很有用。就像在两个进程之间共享对象时一样。

答案 1 :(得分:0)

#include <iostream>
using namespace std;

template<typename T>
class Service {
    struct TT: T {
      using T::initialize;
      using T::terminate;
    };
public:
    Service() {
        if(s_count++ == 0) {
            TT::initialize();
        }
    }

    ~Service() {
        if(--s_count == 0) {
            TT::terminate();
        }
    }

private:
    static int s_count;
};


class Test : public Service<Test> {
    //friend class Service<Test>;

protected:
    static void initialize() {
        std::cout << "Initialized" << std::endl;
    }

    static void terminate() {
        std::cout << "Terminated" << std::endl;
    }
};

template<typename T>
int Service<T>::s_count = 0;


int main() {   
    Test t;
}

答案 2 :(得分:0)

nm建议让这些方法变得虚拟让我觉得:它本身不起作用,但是如果你将服务从它的管理中解耦出来它工作:初始化没有&# 39; t只适用于该特定服务实例,它适用于所有实例,也许正因为如此,它不应该首先成为服务类的一部分。

如果将它们分离,则可以使用派生服务管理器必须实现的虚方法来创建服务管理器基类,如下所示:

#include <iostream>

class ServiceManager {
  template <typename T>
  friend class Service;
  virtual void initialize() = 0;
  virtual void terminate() = 0;
};

template <typename T>
class Service {
public:
  Service() {
    if (s_count++ == 0) {
      s_manager.initialize();
    }
  }
  ~Service() {
    if (--s_count == 0) {
      s_manager.terminate();
    }
  }

private:
  static int s_count;
  static ServiceManager &&s_manager;
};

template <typename T>
int Service<T>::s_count = 0;

template <typename T>
ServiceManager &&Service<T>::s_manager = T();

class TestManager : public ServiceManager {
  void initialize() {
    std::cout << "Initialized" << std::endl;
  }
  void terminate() {
    std::cout << "Terminated" << std::endl;
  }
};

class Test : public Service<TestManager> {
};

如果您的编译器不支持使用&&(它的有效C ++ 11,但不是有效的C ++ 03),那么您仍应该能够轻松地调整代码可以是s_manager ServiceManager &而不是使用临时T来初始化代码,或只是让s_manager具有类型T。前者更冗长,后者允许T实现不是从ServiceManager派生的。