如何处理默认构造函数和重载构造函数之间的歧义



行 A b(3) 会产生歧义,因为它可以调用两个可能的构造函数中的任何一个。单参数参数化构造函数或具有默认参数的双参数参数化构造函数。我该如何解决这个问题?

#include<iostream>
using namespace std;
class A
{
    public:
    int a,b;
    A()
    {
        a=5;
        b=6;
    }
    A(int a1)
    {
        a=a1;
        b=54;
    }
    A(int a1,int b2=8)
    {
        a=a1;
        b=b2;
    }
    void show()
    {
        cout<<"a="<<a<<" b="<<b<<endl;
    }
};    
int main()
{
    A a(3); // I want A(int a1,int b2=8) to get executed
    A b(3); // I want A(int a1) to get executed
    a.show();
    b.show();
    return 0;
} 

首先,回答这个问题:

当你写A a(4)时,你是否希望a.b.是:

选项 a) 54

class A
{
    public:
    int a,b;
    A()
    {
        a=5;
        b=6;
    }
    A(int a1,int b2 = 54)
    {
        a=a1;
        b=b2;
    }
};    

选项 b) 8

class A
{
    public:
    int a,b;
    A()
    {
        a=5;
        b=6;
    }
    A(int a1,int b2 = 8)
    {
        a=a1;
        b=b2;
    }
};    

错误是有原因的。如果您不知道要从代码中得到什么,您怎么能期望编译器这样做呢?

编辑:编辑后 - 不可能。不是那个确切的代码。

你对编译器的要求有歧义。

A(int a1)
{
    a=a1;
    b=54;
}

A(int a1,int b2=8)
{
    a=a1;
    b=b2;
}

当您的类仅由一个参数创建时,是相同的。 首先用英语写下您对课程的期望。 然后,将其转换为 C++ 代码。示例:"如果我的类 A 只用一个参数创建,那么让我的变量 a 等于该参数,让我的变量 b 为 54。如果它是由两个参数创建的,那么将第一个参数交给 a,将第二个参数交给 b",并且此表达式的代码为:

A(int a1,int b2=54)
{
    a=a1;
    b=b2;
}

删除A(int a1)函数,而不是A b(3)调用A b(3, 54)

在您的示例中,当仅使用单个参数调用第二个构造函数时,编译器无法判断您指的是第二个还是第三个构造函数。

通常,如果您需要添加带有其他默认参数的新构造函数,则会使默认值产生与早期构造函数相同的行为并摆脱早期版本,例如,在这种情况下,b2 的默认值必须是 54。或者,不要为新构造函数提供默认参数,而只需要求调用方显式传递它。

我想另一种选择是使用默认构造函数使用多个派生类,这些构造函数将不同的参数传递给基类构造函数。

class A
{
public:
    int a, b;
    A() { a = 5; b = 6; }
    A(int a1) { a = a1; b = 54; }
    A(int a1, int b1) { a = a1; b = b1; }
    ...
};
class B: public A
{
public:
    B(int a1): A(a1, 8) { }
};

希望用 8 而不是 54 初始化 A::b 的代码会创建 B。不过,在许多情况下,这不是一个好的选择。

我删除了构造函数中的默认值 =8 并修复了它。 可以在构造函数的实现中指定 54,但不能指定参数。 否则,它会将其与没有 =8 参数的其他构造函数混淆。