C++避免构造对象
我有一个类,其所有默认构造函数都超出了我的控制范围。我需要避免在某些情况下构建它们,而在其他情况下则不然。有什么我可以做的吗?
模式是这样的:
class A
{
public:
//ctor + dtor + methods
A();
~A();
// Data members beyond my control
X1 x1;
X2 x2;
...
XN xn;
};
class B
{
public:
B()
{}
// Data members
A a; // This instance of A is the issue
};
问题是 X1
到 XN
完全超出了我的控制范围。 A
类只是将 x1
到 xn
打包在一起的类。我想有条件地在 B
中创建 A
的实例。现在的问题是,X1
到 XN
的默认构造函数会执行某些在某些情况下需要避免的操作,而在其他情况下则不需要。因此,无论我是否构造 A
,B
都会尝试使用 A
的默认构造函数创建一个,这反过来又会启动默认值X1
到 XN
的构造函数。这是我需要避免的。
我目前正在使用宏来解决这个问题,但想看看是否有更好的解决方案。
I have an class whose all default constructors are beyond my control. I need to avoid constructing them in some conditions and not in others. Is there any what I can do this ?
The pattern is something like this:
class A
{
public:
//ctor + dtor + methods
A();
~A();
// Data members beyond my control
X1 x1;
X2 x2;
...
XN xn;
};
class B
{
public:
B()
{}
// Data members
A a; // This instance of A is the issue
};
The issue is X1
to XN
are completely beyond my control. Class A
is just a class which packages x1
to xn
together. I want to conditionally create the instance of A
, in B
. Now the issue is that the default constructors of X1
to XN
do something that needs to be avoid under some conditions and not others. So no matter if I construct A
or not, B
will try to create a using the default constructor of A
, which will in turn initiate default constructors of X1
to XN
. This is what I need to avoid.
I am using macros to fix this currently, but wanted to see if there is a better solution out there.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
正如康拉德·鲁道夫指出的:
As Konrad Rudolph pointed out:
您可能想使用 Nullable 类型,例如 boost::Optional。这看起来像:
这回答了问题,但我认为如果你告诉你真正想要实现的目标,可以给出更合适的答案。我觉得这更多是一个设计问题而不是语言问题。接下来是扩展的想法。
在上面的“解决方案”中,
else
子句中包含什么内容?由于A
显然只能默认构造,因此您不能调用不同的构造函数。但是,如果您不初始化a
,则会引入(圈)复杂性,因为这意味着每个方法都必须检查a
是否处于活动状态。或者你可以抛出;然而,我会重构在函数中进行检查(或其他)的代码;私有静态方法或匿名/静态独立函数,如下所示:但是,这假设
A
是可复制的。如果情况并非如此,或者复制A
是不可接受的,我认为第一个解决方案是可以接受的,条件是作为类不变a
的一部分永远不为空。如果我们知道
A
和B
之间的关系,那么推荐一些东西就会更容易。如果您想有条件地初始化A
成员,为什么要将它放入B
中呢?也许两者之间的首选关系不应该是聚合而是关联:指向A
的指针成员(或引用成员,如果您小心赋值运算符),例如:这样就不会引入圈复杂度你并不关心 A 是如何以及何时构建的。该契约给调用者增加了一些负担,但由于我们只能将左值传递给构造函数,因此很难滥用。
You may want to use a Nullable type like boost::optional. This would look like:
This answers the question but I think a more appropriate answer could be given if you told what you really wanted to achieve. I feel this is more of a design issue rather than a language issue. Extended thoughts follow.
In the above 'solution', what goes in the
else
clause? SinceA
can apparently only be default-constructed, it's not like you can put a different constructor call. If you do not however initializea
you introduce (cyclomatic) complexity since that would mean that every method will have to check ifa
is active. Alternatively you could throw; I would however refactor the code that do the checking (or whatever) in a function; either a private static method or an anonymous/static freestanding function like this:This however assumes that
A
is copyable. If that's not the case or it's not acceptable to copyA
around, I'd consider the first solution acceptable on the condition that as part of the class invarianta
is never empty.It'd be easier to recommend something if we knew the relationship between
A
andB
. Why would you put anA
member inB
if you want to conditionally initialize it? Perhaps the preferred relationship between the two should not be aggregation but association: a pointer member (or reference member if you're careful about the assignment operator) toA
such as:That way you introduce no cyclomatic complexity and you don't care how and when an A is constructed. The contract adds a bit of a burden on the caller but since we can only pass lvalues to the constructor it's hard(er) to misuse.
目前还不清楚您想要避免哪种构造函数,但在任何一种情况下您都可以使用联合。
来自 Stroustrup 第 4 版:
因此,如果您不想在 B 中构造 A 时,请使用:
It's unclear which constructor you want to avoid but in either case you can use a union.
From Stroustrup 4th ed:
So if you want to not construct A when it is in B, use: