我有一个带有几个私有成员的基产品类和一个派生类继承的公共getter。我想取消实例化的资格,因为类是用于抽象工厂的。我认为受保护的con/destructors可能会工作,然而,这破坏了我的智能指针。交友似乎是一场有用的灾难。有没有一个众所周知的解决方案,或者我应该接受这样一个事实,即任何注入工厂的客户都必须知道足够的知识来实例化基本产品?
class Product
{
private:
char type_name;
char size_name;
public:
Product(char, char);
virtual ~Product() {}
void Print();
};
使用令牌密钥。
private:
Product(char, char);
struct key_t{explicit key_t(int){}};
static key_t key(){return key_t(0);}
public:
Product(key_t, char a, char b):Product(a,b){}
static std::shared_ptr<Product> make_shared(char a, char b){ return std::make_shared<Product>(key(),a,b); }
任何具有CCD_ 1的人都可以构建CCD_。没有钥匙,你就不能。
这允许Product
将创建权限作为值传递。
具有可配置销毁代码的智能指针可以使用类似的技术。但我会公开销毁程序。
您的静态成员函数或朋友函数(即工厂(在调用受保护的构造函数和返回智能指针方面应该没有问题。通常计划返回一个std::unique_ptr<BaseClass>
,如果调用者想要的话,可以将其转换为std::shared_ptr
。
将虚拟析构函数公开。
更新:不要麻烦把工厂当成朋友。您只需要阻止构造基类和中间类。通过将实现类隐藏在它们自己的源文件中,使它们有效地隐藏和私有。或者我想是一个匿名的命名空间。
以下是我将如何做到这一点的一些代码:
#include <iostream>
#include <memory>
#include <string>
// ITest is the only class any other code file should ever see.
class ITest {
protected:
ITest() = default;
public:
virtual ~ITest() = 0;
virtual int getX() const = 0;
virtual int getY() const = 0;
};
// Destructors must always have an implementation even if they are pure virtual.
ITest::~ITest() {}
std::ostream &operator<<(std::ostream &os, const ITest &x) {
return os << '[' << x.getX() << ',' << x.getY() << ']';
}
// Declaration of constructTest factory function.
// Its definition should be hidden in a cpp file.
std::unique_ptr<ITest> constructTest(int x);
// The main function does not need to know anything except the ITest interface
// class and the constructTest function declaration.
int main(int argc, char *argv[]) {
int val = 0;
if (argc > 1)
val = std::stoi(argv[1]);
auto p = constructTest(val);
std::cout << *p << std::endl;
}
// These classes should be defined in a private header file or in a cpp file.
// Should not be visible to any other code. It has no business knowing.
// Hiding all of this implementation is sort of the point of abstract interface
// classes and factory function declarations.
class TestBase : public ITest {
private:
int x = 0;
int y = 0;
protected:
TestBase(int x = 0, int y = 0) : x(x), y(y){};
public:
int getX() const override { return x; }
int getY() const override { return y; }
};
class TestA final : public TestBase {
public:
TestA() = default;
};
class TestB final : public TestBase {
public:
TestB(int x, int y) : TestBase(x, y) {}
int getX() const override { return -TestBase::getX(); }
};
std::unique_ptr<ITest> constructTest(int x) {
// make_unique is c++14.
// For C++11 use std::unique_ptr<ITest>(new TestB(x, x)
if (x) {
return std::make_unique<TestB>(x, x);
// return std::unique_ptr<ITest>(new TestB(x, x));
}
return std::make_unique<TestA>();
}
答案是让析构函数成为一个纯虚拟AND,用一个空体来实现它。那个空洞的实现就是我被绊倒的地方。Print((不需要是静态的。
产品.hpp
#include <memory>
class Product {
public:
virtual ~Product() = 0;
void Print();
protected:
char type_name{};
char size_name{};
private:
};
产品.cpp
#include "Product.hpp"
Product::~Product() {}
void Product::Print() {
//Print p
}