基于CRTP的Meyers单例模板实现:如何让子类直接调用instance()方法?
当然可以实现!你当前的代码里,Foo是私有继承Singleton<Foo>的,所以Singleton<Foo>的instance()方法在Foo内部是私有访问权限,外部无法直接通过Foo::instance()调用。我们可以通过几种方式解决这个问题,下面逐个说明:
方案1:在子类中添加转发的静态instance()方法
这是最直接的方式,不需要修改Singleton模板,只需要在Foo中新增一个静态方法,直接转发到Singleton<Foo>::instance():
#include <bits/stdc++.h> template <typename T> class Singleton { public: static T& instance() { static T _instance; return _instance; } protected: Singleton() = default; ~Singleton() = default; Singleton(const Singleton & s) = delete; Singleton& operator=(const Singleton & s) = delete; }; class Foo : Singleton<Foo> { public: // 添加转发方法 static Foo& instance() { return Singleton<Foo>::instance(); } void print() { std::cout<<"from the foo singleton count : " <<count++<<std::endl; } private: int count = 0; }; int main () { // 现在可以直接用 Foo::instance() 调用了 Foo::instance().print(); Foo::instance().print(); Foo::instance().print(); return 0; }
优点:不需要改动原有Singleton模板的逻辑,保持了Foo私有继承的特性(隐藏了单例实现细节);缺点:每个单例子类都要重复写一遍这个转发方法,有点冗余。
方案2:将子类改为public继承Singleton<Foo>
如果不介意暴露Foo的单例实现方式,可以把继承权限改为public,这样Singleton<Foo>的public成员instance()会自动成为Foo的public成员:
// Singleton 模板代码不变 class Foo : public Singleton<Foo> { // 改为 public 继承 public: void print() { std::cout<<"from the foo singleton count : " <<count++<<std::endl; } private: int count = 0; }; int main () { Foo::instance().print(); // 直接调用即可 return 0; }
优点:代码最简洁,不需要额外添加任何方法;缺点:外部代码能看到Foo继承了Singleton模板,暴露了单例的实现细节。
方案3:使用using声明引入基类的instance()方法
这是平衡了代码简洁性和隐藏实现细节的最优解——保持私有继承,同时通过using声明把基类的instance()方法引入到子类的public作用域:
// Singleton 模板代码不变 class Foo : Singleton<Foo> { public: // 把基类的 instance() 引入到当前类的 public 域 using Singleton<Foo>::instance; void print() { std::cout<<"from the foo singleton count : " <<count++<<std::endl; } private: int count = 0; }; int main () { Foo::instance().print(); // 正常调用 return 0; }
优点:既保持了私有继承(隐藏实现细节),又不需要写冗余的转发代码,代码简洁且优雅;缺点:需要了解using声明的作用(不过这是C++中很常用的特性)。
以上三种方案都能实现你想要的Foo::instance().print()调用方式,你可以根据自己的需求选择最合适的一种。
内容的提问来源于stack exchange,提问作者wangzj
相关产品推荐
相关产品推荐

