C++类和对象【下】

再谈构造函数

        在创建对象时,编译器可以通过调用构造函数给成员变量赋值,但这并不是初始化,因为初始化只能初始化一次,但是赋值显然可以有多次赋值。

        这里就引入初始化列表概念:

        初始化列表是C++中用来初始化类成员变量的一种语法。它可以在构造函数的初始化列表中指定初始化值,而不是在构造函数的函数体中进行初始化。这种方式可以提高效率并减少代码量。

例如,对于以下类:

class MyClass {
public:
    MyClass(int x, int y) 
     :a(x),
     b(y)
     {}
private:
    int a;
    int b;
};

        构造函数的初始化列表为“: a(x), b(y)” 。这表明在创建MyClass对象时,a的初始值为x,b的初始值为y。如果没有使用初始化列表,构造函数将会像这样:

class MyClass {
public:
    MyClass(int x, int y)
    {
        a = x;
        b = y;
    }
private:
    int a;
    int b;
};

        这种构造函数的效率不如使用初始化列表的高,因为它需要在构造函数的函数体中执行两个赋值操作。在实际应用中,当需要初始化大量成员变量时,使用初始化列表可以明显提高程序的性能。

        注意:

        1、每个成员变量在初始化列表只能出现一次,也就是只能被初始化一次

        2、引用成员变量、const成员变量、自定义类型成员变量(且类没有默认构造函数)必须要在初始化列表初始化。

        3、成员变量的声明顺序就是初始化列表的初始顺序,与其在初始化列表中的顺序无关

explicit关键字

        在C++中,explicit是一个关键字,用于修饰单参数构造函数。它的作用是防止隐式类型转换,即只能通过显式调用构造函数来进行对象的构造,而不能通过隐式转换来构造对象。

        举一个例子,考虑下面这个类:

class MyClass {
public:
    MyClass(int x) : a(x) {}
private:
    int a;
};

        如果我们定义一个函数,需要传入一个MyClass对象作为参数,那么这个函数可以这样声明:

void func(MyClass obj);

        如果我们传入一个int类型的参数给这个函数,那么编译器会自动进行类型转换,将这个int类型的参数转换为一个MyClass对象。

func(5); // 会自动转换为 func(MyClass(5))

        但是,如果我们在MyClass的构造函数前加上explicit关键字,就能禁止隐式类型转换。那么上述代码就会编译错误,必须要显式地创建一个MyClass对象才能传入函数:

class MyClass {
public:
    explicit MyClass(int x) : a(x) {}
private:
    int a;
};

func(MyClass(5)); // 正确的写法
func(5); // 编译错误,不能隐式转换

        使用explicit关键字可以避免一些不必要的隐式类型转换,使代码更加明确和健壮。但需要注意的是,如果在实际应用中过度使用explicit可能会导致代码变得冗长和难懂。

static成员

概念:声明为static的类成员,称为静态成员,用static修饰的函数称为静态成员函数。静态成员变量一定要在外面进行初始化。

class test
{
private://定义静态成员变量
	static int _a;
};
//在类外部进行赋值
int test::_a = 0;

静态成员变量与函数的特性:

        1. 静态成员为所有类对象所共享,不属于某个具体的对象,存放在静态区
        2. 静态成员变量必须在类外定义,定义时不添加static关键字,类中只是声明
        3. 类静态成员即可用 类名::静态成员 或者 对象.静态成员 来访问
        4. 静态成员函数没有隐藏的this指针,不能访问任何非静态成员
        5. 静态成员也是类的成员,受public、protected、private 访问限定符的限制

class MyClass {
public:
    static int count;
};

int MyClass::count = 0;  // 定义静态数据成员

int main() {
    MyClass obj1, obj2;
    MyClass::count++;  // 通过类名访问静态数据成员
    obj1.count++;     // 通过对象名访问静态数据成员
    obj2.count++;
    cout << "Count: " << MyClass::count << endl; // 输出3
}
 

        静态成员函数是指在类中声明的静态函数,它不属于任何对象,而属于整个类。静态成员函数可以使用类的静态数据成员,但不能使用类的非静态数据成员和成员函数。静态成员函数可以通过类名访问,也可以通过对象名访问。例如:

class MyClass {
public:
    static void foo() {
        cout << "This is a static member function." << endl;
    }
};

int main() {
    MyClass::foo();  // 通过类名调用静态成员函数
    MyClass obj;
    obj.foo();       // 通过对象名调用静态成员函数
}
 

        静态成员可以在类中被用来表示某个类相关的信息或者状态,常用于记录对象的数目、实现单例模式等。使用静态成员需要注意生命周期和作用域问题,以及与非静态成员的区别。

友元

        友元是C++中的一个特殊机制,它可以让某个函数或类访问一个类的私有成员。可以说友元是一种授权机制,它允许外部程序或者其他类访问当前类的私有成员。

        友元可以是一个函数、一个类、或者一个函数模板。友元声明通常出现在类定义中,并在类定义体外进行定义。友元有两种类型:普通友元和类友元。

        普通友元可以是一个全局函数或者一个类的成员函数,可以访问当前类的所有成员,包括私有成员。例如:

class A {
public:
    int a;
    friend void foo(A obj) {
        cout << "a = " << obj.a << endl;
    }
};

int main() {
    A obj;
    obj.a = 10;
    foo(obj);  // 调用友元函数
    return 0;
}

        类友元可以让另一个类访问当前类的私有成员,即两个类之间建立友好关系。类友元通常在另一个类的定义中进行声明,并在类定义体外进行定义。例如:

class B;

class A {
private:
    int a;
public:
    friend class B;
};

class B {
public:
    void foo(A obj) {
        cout << "a = " << obj.a << endl;
    }
};

int main() {
    A obj;
    B b1;
    b1.foo(obj);  // 调用类友元函数
    return 0;
}

        需要注意的是,友元机制会降低封装性,不当使用会导致安全问题。因此,应该慎重使用友元机制,只在必要的情况下使用。

        内部类

        概念:如果一个类定义在另一个类的内部,这个内部类就叫做内部类。内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去访问内部类的成员。外部类对内部类没有任何优越的访问权限。
        注意:内部类就是外部类的友元类,参见友元类的定义,内部类可以通过外部类的对象参数来访问外部类中的所有成员。但是外部类不是内部类的友元。
        特性:

1. 内部类可以定义在外部类的public、protected、private都是可以的。
2. 注意内部类可以直接访问外部类中的static成员,不需要外部类的对象 / 类名。
3. sizeof(外部类) = 外部类,和内部类没有任何关系。

class A
{
private:
	static int k;
	int h;
public:
	class B // B天生就是A的友元
	{
	public:
		void foo(const A& a)
		{
			cout << k << endl;//OK
			cout << a.h << endl;//OK
		}
	};
};
int A::k = 1;
int main()
{
	A::B b;
	b.foo(A());

	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值