0.可以吗?
我们不能让构造函数变成virtual的。C++语言的创造者stroustrup博士给出了很好的解释:virtual是一项使用部分信息就完成工作的技术,我们在调用virtual function时,只需要知道他的接口,而不需要知道他的具体对象。而构造函数在调用时需要知道对象的所有信息,这与virtual的技术相悖。
1.间接实现virtual constructor
我们可以在类中提供一个创建对象的virtual function来实现这个功能,例如:
class Expr r {
public:
Expr() ; / / default constructor
Expr(const Expr&) ; / / copy constructor
virtual Expr* ne w_expr() { return ne w Expr() ; }
virtual Expr* clone() { return ne w Expr(*this) ; }
};
将构造对象的member function设成virtual的,他就是"virtual constructor"。
2.factory design pattern
假设library端提供一个方法,client端只需要提供简单的信息,就可以完成对应的操作,同时对client端完全隐藏library端的信息,这就是factory design pattern,他是利用virtual来实现的,看一个简单的例子:
//factory.h
namespace design_pattern {
enum class shape_cate {
SQUARE,
ROUND,
};
class shape {
public:
virtual ~shape();
virtual void draw() const = 0;
static shape* createShape(shape_cate cate);
};
class square :public shape {
public:
virtual void draw() const override;
~square();
};
class round :public shape {
public:
virtual void draw()const override;
~round();
};
class user {
public:
user(shape_cate cate);
void drawTheShape()const;
~user();
private:
shape_cate c_;
shape* s_ = nullptr;
};
}
//factory.cpp
namespace design_pattern {
shape::~shape() {
}
shape* shape::createShape(shape_cate cate) {
if (cate == shape_cate::SQUARE) {
return new square();
}
else if (cate == shape_cate::ROUND) {
return new round();
}
else {
return nullptr;
}
}
void square::draw() const {
std::cout << "-----" << std::endl;
std::cout << "| |" << std::endl;
std::cout << "| |" << std::endl;
std::cout << "-----" << std::endl;
}
square::~square() {
std::cout << "delete square" << std::endl;
}
void round::draw() const {
std::cout << "round" << std::endl;
}
round::~round() {
std::cout << "delete round" << std::endl;
}
user::user(shape_cate cate) {
s_ = shape::createShape(cate);
}
void user::drawTheShape() const {
if (s_) {
s_->draw();
}
}
user::~user() {
if (s_) {
delete s_;
s_ = nullptr;
}
}
}
client端只需要提供图形的类型,利用library端提供的一个static方法,就可以构造不同的shape,调用他们去做一些工作,而client完全不知道他构造的square是什么样的。如果library端再次添加新的图形,client端也不需要更改任何代码。据高手们说,这种就叫decoupling,听上去好高级😄。
参考文献
[1]why do we not have a virtual constructor in c++
[2]Stroustrup B. The C++ Programming Language, Third Edition[C]// 1997.
[3]factory method