C++ - 构造函数重载 - 私有和公共

Posted

技术标签:

【中文标题】C++ - 构造函数重载 - 私有和公共【英文标题】:C++ - Constructor overloading - private and public 【发布时间】:2010-10-13 06:25:59 【问题描述】:

你能告诉我为什么下面的代码给我下面的错误 - 重载“C(int)”的调用不明确

我认为由于 C(char x) 是私有的,因此只有 C(float) ctor 从外部可见,应该通过将 int 转换为 float 来调用它。

但事实并非如此。

class C

    C(char  x)
    
    
public:
    C(float t)
    
    
;

int main()

    C p(0);

【问题讨论】:

【参考方案1】:

Scott Meyer 在“Effective C++”中对此进行了讨论。之所以模棱两可,是因为他们希望确保仅仅改变成员的可见性不会改变其他地方已经存在的代码的含义。

否则,假设您的 C 类位于某个标题中。如果您有一个私有 C(int) 成员,那么您提供的代码将调用 C(float)。如果由于某种原因 C(int) 成员被公开,旧代码会突然调用该成员,即使 旧代码和它调用的函数都没有改变

编辑:更多原因:

更糟糕的是,假设您有以下 2 个函数:

C A::foo() 

    return C(1.0);


C B::bar() 

    return C(1.0);

这两个函数可以调用不同的函数,具体取决于 foo 或 bar 是否被声明为 C 的友元,或者 A 或 B 是否继承自 C。 相同的代码调用不同的函数是可怕的。

(这可能不如 Scott Meyer 的讨论那么好,但这就是想法。)

【讨论】:

嗯,起初这似乎是一个很好的解释。但是......仍然可以创建类没有一个int-ctor,然后添加那个ctor所以旧代码突然开始调用新成员......所以这个保护只会产生虚假的安全感。【参考方案2】:

0 是 int 类型。因为它可以同等地隐式转换为 float 或 char,所以调用是不明确的。 可见性与这些目的无关。

要么放置0.00.0.0f,要么完全摆脱C(char) 构造函数。

编辑:标准的相关部分,第 13.3 节:

3) [...] 但是,一旦确定了候选函数和参数列表,最佳函数的选择在所有情况下都是相同的:

首先,选择候选函数的子集(具有适当数量的参数并满足某些其他条件的函数)以形成一组可行函数 (13.3.2)。 然后根据将每个参数与每个可行函数的相应参数匹配所需的隐式转换序列 (13.3.3.1) 选择最佳可行函数。

4) 如果存在最佳可行函数并且是唯一的,则重载解析成功并生成它作为结果。否则重载解析失败并且调用格式错误。当重载决议成功,并且最佳可行函数在使用它的上下文中不可访问(第 11 条)时,程序是非良构的。

请注意,可见性不是选择过程的一部分。

【讨论】:

您没有说明为什么隐私不会影响重载决议。 +1 这是故事的一半,但没有解决可见性问题 有时在标准中做出决定的原因有历史记录,但不要因为某人告诉它的方式而抨击它。 次要的 nitpick:它没有被提升,但转换为 char 或 float。区别很重要。促销优先于转换。从转换为其他东西,您只能转换。但是如果你通过了一个short,那么如果你有一个int和一个char作为重载,那么int是首选(促销)。 要点是提升扩大(如在 char -> int 中),但转换(转换是一般的。当明确表示“积分转换”时,它不包括提升)不喜欢 int->float。规则有时更精确:bool->long 是整数转换,但 bool->int 是整数提升。【参考方案3】:

我不这么认为:

C p(0);

正在转换为:

C(float t)

你可能需要这样做:

C p(0.0f);

【讨论】:

不,这不是问题所在。从0 到浮点的隐式转换确实 存在。

以上是关于C++ - 构造函数重载 - 私有和公共的主要内容,如果未能解决你的问题,请参考以下文章

重载赋值运算符

C++复制构造函数和=号重载问题

C++历史

c++中拷贝构造函数和赋值运算符重载本质上一样么

黑马程序员 C++教程从0到1入门编程笔记4C++核心编程(类和对象——封装权限对象的初始化和清理构造函数析构函数深拷贝浅拷贝初始化列表友元friend运算符重载)

C++:如何为多个重载函数保留公共代码路径?