调用函数时首选错误的参数转换

时间:2009-03-19 19:39:30

标签: c++ constructor arguments vc6

我正在使用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 *时,它似乎更倾向于从boolRWCString的转换,const char *有一个复制构造函数,需要strPath。为什么这样做?我认为如果有两个可能的选择,就会说这是不明确的。我该怎么做才能阻止它这样做?如果可能的话,我想避免显式地将RWCString参数强制转换为{{1}},因为它将与文字一起使用很多,而且还有很多额外的输入(加上一个很容易犯错误。)

7 个答案:

答案 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*.添加另一个构造函数是否可行?