📜  C ++ |构造函数|问题16(1)

📅  最后修改于: 2023-12-03 15:29:42.463000             🧑  作者: Mango

C++ | 构造函数 | 问题16

在 C++ 中,构造函数是一种特殊的成员函数,用于在对象被创建时初始化对象的数据成员。本文将介绍 C++ 中的构造函数以及一些常见的问题。

构造函数的定义和使用

构造函数是与类同名的特殊成员函数,没有返回类型,不用显式调用,当对象被创建时自动调用。构造函数的作用是初始化对象的数据成员,保证对象的状态是有效的。

class Person {
public:
    Person() {
        name = "";
        age = 0;
    }
    Person(string n, int a) {
        name = n;
        age = a;
    }
private:
    string name;
    int age;
};

int main() {
    Person p1; // 调用无参构造函数
    Person p2("Bob", 21); // 调用有参构造函数
    return 0;
}

在上面示例中,我们定义了一个 Person 类,它包含一个默认的无参构造函数和一个带参构造函数。当我们创建 Person 类的对象时,构造函数会自动调用,初始化 nameage 数据成员。

构造函数的分类
默认构造函数

如果没有显式定义构造函数,则编译器会为类自动生成默认构造函数。默认构造函数无参,没有函数体,只是简单地初始化所有数据成员的值。如果类中没有数据成员,则默认构造函数是空的。

class Point {
public:
    Point(); // 默认构造函数,如果不定义,编译器会自动生成一个
private:
    int x, y;
};

Point::Point() {
    x = y = 0;
}

int main() {
    Point p; // 调用默认构造函数
    return 0;
}
拷贝构造函数

拷贝构造函数是一种特殊的构造函数,它的参数是一个对象的引用,用于将一个对象的值拷贝到另一个对象中。当我们对一个对象进行拷贝构造时,会调用该对象的拷贝构造函数。

class String {
public:
    String(const String& s) {
        len = s.len;
        str = new char[len];
        strcpy(str, s.str);
    }
private:
    int len;
    char* str;
};

int main() {
    String s1("hello");
    String s2(s1); // 调用拷贝构造函数
    return 0;
}
带参构造函数

带参构造函数是指具有参数的构造函数,用于在创建对象时初始化数据成员的值。通过使用带参构造函数,我们可以灵活地创建不同状态的对象。

class Rectangle {
public:
    Rectangle(int w, int h) {
        width = w;
        height = h;
    }
private:
    int width, height;
};

int main() {
    Rectangle r1(10, 20); // 调用带参构造函数
    Rectangle r2 = Rectangle(30, 40); // 等价于上一句
    return 0;
}
隐式调用构造函数

在一些特殊情况下,C++ 会隐式调用构造函数。例如,当我们用一个类对象初始化一个新的对象时,会隐式调用拷贝构造函数。当我们用一个类对象作为函数参数传递给另一个函数时,也会隐式调用拷贝构造函数。

Point p(1, 2);
Point q = p; // 隐式调用拷贝构造函数
void func(Point p); // 声明函数
func(p); // 隐式调用拷贝构造函数
常见问题
默认构造函数和无参构造函数有什么区别?

默认构造函数是没有参数的构造函数,而无参构造函数是指没有参数并且没有函数体的构造函数。默认构造函数可以由编译器自动生成,而无参构造函数必须显式定义。如果我们同时定义了默认构造函数和无参构造函数,则编译器会优先调用无参构造函数。

class Person {
public:
    Person(); // 无参构造函数
private:
    string name;
    int age;
};

Person::Person() {
    name = "";
    age = 0;
}

int main() {
    Person p1; // 调用无参构造函数
    Person p2(); // 声明一个函数,而非调用无参构造函数
    return 0;
}
如果一个类有多个构造函数,它们之间有什么区别?

如果一个类有多个构造函数,它们之间的区别在于它们的参数列表不同。当我们创建一个对象时,编译器会根据参数列表来确定调用哪个构造函数。如果我们没有指定参数,则会调用默认构造函数或无参构造函数。

class Person {
public:
    Person(); // 无参构造函数
    Person(string n, int a); // 带参构造函数
private:
    string name;
    int age;
};

Person::Person() {
    name = "";
    age = 0;
}

Person::Person(string n, int a) {
    name = n;
    age = a;
}

int main() {
    Person p1; // 调用无参构造函数
    Person p2("Bob", 21); // 调用带参构造函数
    return 0;
}
构造函数可以被继承吗?

构造函数不能被继承,但是派生类可以调用基类的构造函数来初始化基类的数据成员。如果派生类没有显式调用基类的构造函数,则会调用默认构造函数或者无参构造函数。

class Animal {
public:
    Animal(string n) {
        name = n;
    }
private:
    string name;
};

class Cat : public Animal {
public:
    Cat(string n, int a) : Animal(n) { // 调用基类的构造函数
        age = a;
    }
private:
    int age;
};

int main() {
    Cat c("Tom", 3);
    return 0;
}