使用工厂时如何 "hide" 构造函数?
How to "hide" constructor when using a factory?
我遇到了一种情况,我想从构造函数中调用虚方法。这当然是不可能的(或者至少它不会产生所需的行为)。 In this answer 作为变通方法,建议使用工厂方法。我写了这样的东西:
#include <iostream>
class Base {
public:
Base(){}
~Base(){}
// private: ??
virtual void afterConstruction()=0;
};
class Derived : public Base {
public:
Derived() : Base() {}
//private: ??
void afterConstruction(){std::cout<<"construct"<<std::endl;}
};
template <typename T> T MyFactory(){
T t = T();
T* p = &t;
p->afterConstruction();
return t;
}
int main(int argc, char** argv) {
Derived d = MyFactory<Derived>();
return 0;
}
这是一种模板方法模式。每个派生 class 都可以自定义其构建方式。但是,只有当此 classes 的用户无法直接调用构造函数或 afterConstruction()
时,整个构造才有意义。因此,我想将它们都设为私有。也许这是一个愚蠢的问题,我只是没有看到明显的问题。也许我可以通过使用友谊或类似的东西来实现这一点,但我不确定这是否是最好的方法。隐藏这两个方法并只允许通过工厂方法创建对象的好方法是什么?
编辑:
Ka7Im1011 让我意识到我的要求并不是很清楚。因此,我将尝试澄清:
我想写一个基础 class 其他人必须从中派生。构建派生对象涉及非常具体的内容,我想将其排除在基础 class 之外。在网上搜索虚拟构造函数时,我发现了上面提到的问答,我认为工厂方法可以很好地工作。但是,我不确定如何实现以下目标:
- 应该只能创建从工厂派生的实例。否则,派生对象可能会以不一致的状态创建。 (我想我不能单独在基础 class 中强制执行此操作,但要求 Derived 的每个编码器制作构造函数 private/protected 就足够了。)
- 如果可能,Derived 应该只实现 Base 的纯虚方法,因为这样写 Derived 会很舒服(IDEs/compilers 将准确说明必须实现的内容,而不是冗长且有时是神秘的错误消息当例如必须实现模板参数的接口时)
我不太明白你的问题,但你可能正在寻找这个。
#include <iostream>
#include <conio.h>
class Base
{
virtual void afterConstruction() = 0;
};
class Derived : Base {
private:
Derived() : Base() {}
public:
void afterConstruction(){ std::cout << "construct" << std::endl; }
protected:
static Derived GetInstance()
{
return Derived();
}
};
template <class T> class MyFactory : T
{
public:
static T GetInstance()
{
// Make sure every kind of T has protected GetInstance()
T t = T::GetInstance();
T* p = &t;
p->afterConstruction();
return t;
}
};
int main(int argc, char** argv) {
Derived d = MyFactory<Derived>::GetInstance();
// Derived d1; // will cause error
_getch();
return 0;
}
已编辑答案
#include <iostream>
#include <conio.h>
class Base
{
protected:
Base() { }
virtual void afterConstruction() = 0;
virtual Base* GetInstance() = 0;
};
class Derived : public Base {
protected:
Derived() : Base() { }
void afterConstruction()
{
static bool bConstrucred = false;
if (!bConstrucred)
{
std::cout << "construct" << std::endl;
bConstrucred = true;
}
}
Derived* GetInstance()
{
afterConstruction();
return this;
}
};
template <class T> class MyFactory : public T
{
public:
T* GetInstance() { return T::GetInstance(); }
};
int main(int argc, char** argv) {
Derived* d = MyFactory<Derived>().GetInstance();
// Derived d1; // will cause error
_getch();
return 0;
}
我遇到了一种情况,我想从构造函数中调用虚方法。这当然是不可能的(或者至少它不会产生所需的行为)。 In this answer 作为变通方法,建议使用工厂方法。我写了这样的东西:
#include <iostream>
class Base {
public:
Base(){}
~Base(){}
// private: ??
virtual void afterConstruction()=0;
};
class Derived : public Base {
public:
Derived() : Base() {}
//private: ??
void afterConstruction(){std::cout<<"construct"<<std::endl;}
};
template <typename T> T MyFactory(){
T t = T();
T* p = &t;
p->afterConstruction();
return t;
}
int main(int argc, char** argv) {
Derived d = MyFactory<Derived>();
return 0;
}
这是一种模板方法模式。每个派生 class 都可以自定义其构建方式。但是,只有当此 classes 的用户无法直接调用构造函数或 afterConstruction()
时,整个构造才有意义。因此,我想将它们都设为私有。也许这是一个愚蠢的问题,我只是没有看到明显的问题。也许我可以通过使用友谊或类似的东西来实现这一点,但我不确定这是否是最好的方法。隐藏这两个方法并只允许通过工厂方法创建对象的好方法是什么?
编辑: Ka7Im1011 让我意识到我的要求并不是很清楚。因此,我将尝试澄清:
我想写一个基础 class 其他人必须从中派生。构建派生对象涉及非常具体的内容,我想将其排除在基础 class 之外。在网上搜索虚拟构造函数时,我发现了上面提到的问答,我认为工厂方法可以很好地工作。但是,我不确定如何实现以下目标:
- 应该只能创建从工厂派生的实例。否则,派生对象可能会以不一致的状态创建。 (我想我不能单独在基础 class 中强制执行此操作,但要求 Derived 的每个编码器制作构造函数 private/protected 就足够了。)
- 如果可能,Derived 应该只实现 Base 的纯虚方法,因为这样写 Derived 会很舒服(IDEs/compilers 将准确说明必须实现的内容,而不是冗长且有时是神秘的错误消息当例如必须实现模板参数的接口时)
我不太明白你的问题,但你可能正在寻找这个。
#include <iostream>
#include <conio.h>
class Base
{
virtual void afterConstruction() = 0;
};
class Derived : Base {
private:
Derived() : Base() {}
public:
void afterConstruction(){ std::cout << "construct" << std::endl; }
protected:
static Derived GetInstance()
{
return Derived();
}
};
template <class T> class MyFactory : T
{
public:
static T GetInstance()
{
// Make sure every kind of T has protected GetInstance()
T t = T::GetInstance();
T* p = &t;
p->afterConstruction();
return t;
}
};
int main(int argc, char** argv) {
Derived d = MyFactory<Derived>::GetInstance();
// Derived d1; // will cause error
_getch();
return 0;
}
已编辑答案
#include <iostream>
#include <conio.h>
class Base
{
protected:
Base() { }
virtual void afterConstruction() = 0;
virtual Base* GetInstance() = 0;
};
class Derived : public Base {
protected:
Derived() : Base() { }
void afterConstruction()
{
static bool bConstrucred = false;
if (!bConstrucred)
{
std::cout << "construct" << std::endl;
bConstrucred = true;
}
}
Derived* GetInstance()
{
afterConstruction();
return this;
}
};
template <class T> class MyFactory : public T
{
public:
T* GetInstance() { return T::GetInstance(); }
};
int main(int argc, char** argv) {
Derived* d = MyFactory<Derived>().GetInstance();
// Derived d1; // will cause error
_getch();
return 0;
}