我正在使用MS Visual C ++ 6.0编写程序(是的,我知道它很古老,没有什么我可以做的升级)。我看到一些我认为非常奇怪的行为。我有一个类,有两个构造函数定义如下:
class MyClass
{
public:
explicit MyClass(bool bAbsolute = true, bool bLocation = false) : m_bAbsolute(bAbsolute), m_bLocation(bLocation) { ; }
MyClass(const RWCString& strPath, bool bLocation = false);
private:
bool m_bAbsolute;
bool m_bLocation;
};
当我使用以下语法实例化此类的实例时:MyClass("blah")
,它调用第一个构造函数。正如您所看到的,我添加了explicit
关键字,希望它不会那样做......没有骰子。在转换为const char *
时,它似乎更倾向于从bool
到RWCString
的转换,const char *
有一个复制构造函数,需要strPath
。为什么这样做?我认为如果有两个可能的选择,就会说这是不明确的。我该怎么做才能阻止它这样做?如果可能的话,我想避免显式地将RWCString
参数强制转换为{{1}},因为它将与文字一起使用很多,而且还有很多额外的输入(加上一个很容易犯错误。)
答案 0 :(得分:9)
Explicit在这里没有帮助,因为构造函数不是隐式转换的一部分,只是收件人。
无法控制首选的转换顺序,但您可以添加第二个带有const char *的构造函数。 E.g:
class MyClass
{
public:
MyClass(bool bAbsolute = true, bool bLocation = false);
MyClass(const RWCString& strPath, bool bLocation = false);
MyClass(const char* strPath, bool bLocation = false);
private:
bool m_bAbsolute;
bool m_bLocation;
};
答案 1 :(得分:6)
Andrew Grant提供了解决方案。我想告诉你为什么它不会像你尝试的那样工作。如果你有两个可行的参数函数,那么调用与参数匹配最好的函数。第二个需要用户定义的转换,而第一个只需要标准转换。这就是为什么编译器首选第一个。
答案 2 :(得分:1)
如果你不想继续施展它,那么在我看来你可能不得不制造另一个带有const char *的ctor。
这就是我在这种情况下可能会做的事情。
(不确定为什么要制作一个你没有通过大部分用途的类型的ctor。)
编辑:
我在打字时看到其他人已发布此内容
答案 3 :(得分:0)
不确定为什么它应该混淆对字符串和bool的引用?我看到bool和int的问题 你能否丢失第一个构造函数的默认值 - 可能是因为这使它成为MyClass()的默认构造函数,如果它不能与args匹配,它也是默认值
答案 4 :(得分:0)
您的选择是添加一个显式获取const char *
的构造函数MyClass(const char* strPath, bool bLocation = false); // Thanks Andrew Grant!
或者做
MyClass( string("blah") );
编译器本质上知道如何将const char *变成bool。它必须要查看,对于任何第一个参数类型的MyClass构造函数,是否有一个构造函数将采用您给定的源类型,或者它是否可以将其转换为接受的类型任何MyClass构造函数的第一个参数类型的任何构造函数,或者......好吧,你会看到它的去向,而且只能用于第一个参数。那种方式就是疯狂。
答案 5 :(得分:0)
explicit
关键字告诉编译器它不能隐式地将参数类型的值转换为类的对象,如
struct C { explicit C( int i ): m_i(i) {}; int m_i; };
C c = 10;//disallowed
C c( 2.5 ); // allowed
C ++有一套规则来确定在你的情况下要调用什么构造函数 - 我不知道从后面开始,但你可以直观地看到默认参数导致歧义。
您需要考虑这些默认值。
您可以回退到一些静态的,命名的构造方法。或者您可以使用不同的类(从设计角度来看,这不是一个糟糕的选择)。无论哪种方式,您都可以让客户端代码决定使用哪个构造函数。
struct C {
static C fromString( const char* s, const bool b = true );
static C fromBools( const bool abs = true, const bool b = true );
};
或
struct CBase {
bool absolute;
bool location;
CBase( bool abs=true, bool loc=true );
};
struct CBaseFromPath {
// makes 'absolute' true if path is absolute
CBaseFromPath( const char* s, const bool loc );
};
答案 6 :(得分:-1)
你是某些它真的在调用第一个构造函数吗?你是用字符串硬编码来调用它,还是隐藏在#define
后面?你确定#define是你认为的吗? (尝试使用/ Ef选项进行编译以获得扩展的预处理器输出,并查看调用是否看起来像您期望的那样。)
编辑:根据这个和其他评论,我的建议是为const char*.
添加另一个构造函数是否可行?