C++笔记之智能指针和单例、依赖注入结合使用
code review!
 
文章目录
- C++笔记之智能指针和单例、依赖注入结合使用
 - 例1.一个类不使用单例,另一个类使用单例
 - 例2.两个类都使用单例,并且通过getInstance()传入类的实例
 - 例3.std::make_unique不能访问私有的构造函数
 - 例4.不通过友元,通过静态成员函数在类外部调用类私有的构造函数
 

例1.一个类不使用单例,另一个类使用单例

运行
 
代码
#include <iostream>
#include <memory>
class Logger {
private:
    Logger() {}  // 私有构造函数,防止外部实例化
public:
    static Logger& getInstance() {
        static Logger instance;  // 静态局部变量确保只有一个实例
        return instance;
    }
    void log(const std::string& message) {
        std::cout << "Log: " << message << std::endl;
    }
};
class Service {
private:
    std::shared_ptr<Logger> logger;
public:
    Service(std::shared_ptr<Logger> logger) : logger(logger) {}
    void doSomething() {
        logger->log("Service is doing something.");
    }
};
int main() {
    // 在依赖注入的方式下,创建 Service 实例并传入 Logger 实例
    Service service(std::make_shared<Logger>(Logger::getInstance()));
    // 使用 Service 实例
    service.doSomething();
    return 0;
}
 
例2.两个类都使用单例,并且通过getInstance()传入类的实例

运行
 
代码
#include <iostream>
#include <memory>
class Logger {
  private:
    Logger() {} // 私有构造函数,防止外部实例化
  public:
    static std::shared_ptr<Logger> getInstance() {
        static std::shared_ptr<Logger> instance = std::shared_ptr<Logger>(new Logger());
        return instance;
    }
    void log(const std::string &message) {
        std::cout << "Log: " << message << std::endl;
    }
};
class Service {
  private:
    std::shared_ptr<Logger> logger;
    Service(const std::shared_ptr<Logger> &logger) : logger(logger) {}
  public:
    static std::shared_ptr<Service> getInstance(const std::shared_ptr<Logger> &logger) {
        static std::shared_ptr<Service> instance = std::shared_ptr<Service>(new Service(logger));
        return instance;
    }
    void doSomething() {
        logger->log("Service is doing something.");
    }
};
int main() {
    // 创建 Logger 实例(智能指针管理)
    std::shared_ptr<Logger> logger = Logger::getInstance();
    // 创建 Service 实例并传入 Logger 实例
    std::shared_ptr<Service> service = Service::getInstance(logger);
    // 使用 Logger 实例
    logger->log("Logging from main");
    // 使用 Service 实例
    service->doSomething();
    return 0;
}
 
例3.std::make_unique不能访问私有的构造函数

编译报错:
 
这段代码存在一些小问题:
在 Service 类的 getInstance 方法中,你使用了 std::make_unique 来创建一个 Service 实例,但是 Service 的构造函数是私有的,不能直接使用 make_unique。你应该改用 std::shared_ptr<Service>(new Service(logger)) 来创建实例,就像在 Logger 类中的 getInstance 方法中一样。
代码
#include <iostream>
#include <memory>
class Logger {
  private:
    Logger() {} // 私有构造函数,防止外部实例化
  public:
    static std::shared_ptr<Logger> getInstance() {
        static std::shared_ptr<Logger> instance = std::shared_ptr<Logger>(new Logger());
        return instance;
    }
    void log(const std::string &message) {
        std::cout << "Log: " << message << std::endl;
    }
};
class Service {
  private:
    std::shared_ptr<Logger> logger;
    Service(const std::shared_ptr<Logger> &logger) : logger(logger) {}
  public:
    static std::shared_ptr<Service> getInstance(const std::shared_ptr<Logger> &logger) {
        static std::shared_ptr<Service> instance = std::make_unique<Service>(logger);
        return instance;
    }
    void doSomething() {
        logger->log("Service is doing something.");
    }
};
int main() {
    // 创建 Logger 实例(智能指针管理)
    std::shared_ptr<Logger> logger = Logger::getInstance();
    // 创建 Service 实例并传入 Logger 实例
    std::shared_ptr<Service> service = Service::getInstance(logger);
    // 使用 Logger 实例
    logger->log("Logging from main");
    // 使用 Service 实例
    service->doSomething();
    return 0;
}
 
例4.不通过友元,通过静态成员函数在类外部调用类私有的构造函数

运行
 
将实例的创建和初始化封装在了名为 createInstance 的公共静态成员函数中。这个函数在类的外部被调用时,会调用私有构造函数创建一个实例,并返回一个指向这个实例的智能指针。
通过这种方式,你不需要将 std::make_unique 声明为友元函数,也不需要使用特定的友元声明。而是通过公共静态成员函数间接地在类的外部创建实例,从而绕过了直接访问私有构造函数的问题。
构造函数不是静态成员,它们属于实例化的过程,而不是类本身的静态成员。
在C++中,构造函数不是静态成员,它们是用于创建类的实例的特殊成员函数。私有构造函数意味着不能在类的外部直接调用它来创建实例。这是单例模式的一个关键概念,它确保只有一个实例被创建。
而使用公共静态成员函数(如 createInstance)的优势在于,它可以在类的外部创建实例。这是因为静态成员函数不依赖于特定实例,所以它们可以在没有创建对象的情况下被调用。通过在公共静态成员函数中调用私有构造函数,你可以在类的外部创建类的实例。
所以,使用公共静态成员函数解决单例模式中私有构造函数访问问题的关键在于,它提供了一种通过类的内部机制(即静态成员函数)来间接创建实例的方式,绕过了私有构造函数不能直接在外部调用的限制。
代码
#include <iostream>
#include <memory>
class Dependency {
  public:
    void doSomething() {
        std::cout << "Dependency is doing something." << std::endl;
    }
};
class Singleton {
  private:
    Singleton() { /* 构造函数私有化 */
    }
    static std::unique_ptr<Singleton> instance;
    std::unique_ptr<Dependency> dependency; // 保存依赖项的指针
  public:
    // 创建 Singleton 实例的公共静态函数
    static std::unique_ptr<Singleton> createInstance() {
        return std::unique_ptr<Singleton>(new Singleton);
    }
    // 获取 Singleton 实例的公共静态函数
    static Singleton &getInstance() {
        if (!instance) {
            instance = createInstance();                           // 创建实例
            instance->dependency = std::make_unique<Dependency>(); // 初始化依赖项
        }
        return *instance;
    }
    void useDependency() {
        dependency->doSomething();
    }
    // 其他成员函数
};
// 初始化静态成员变量
std::unique_ptr<Singleton> Singleton::instance = nullptr;
int main() {
    // 创建 Singleton 实例
    std::unique_ptr<Singleton> singleton = Singleton::createInstance();
    // 使用注入的依赖项进行操作
    singleton->useDependency();
    return 0;
}
                


















