类和对象(下)

目录

构造函数的初始化列表

隐式类型转换

static成员

友元

内部类

匿名对象

构造函数的初始化列表

在之前说过构造函数时,都是在函数体中进行初始化,构造函数也可以在初始化列表中进行对初始化操作,这样就使构造函数看着更加简洁美观。

初始化列表的使用方式是在函数括号的后面加上冒号,用逗号隔开以形成列表,对成员对象进行赋值初始化

在值括号中可放值或者表示式,而每个成员变量在初始化列表中只能出现一次。

在初始化列表中没有出现的成员变量,C++11支持缺省值给那些没出现在初始化列表的变量初始化,如果说某个变量又有缺省值又有初始化列表,那么它的值最终就是初始化列表的值。

引用成员变量、const成员变量、没有默认构造的类类型变量,必须放在初始化列表位置进行赋值,否则会引发编译报错。

成员变量最终都会在初始化列表中进行初始化 ,如果设置缺省值,才会使用缺省值,但是如果没有缺省值,没有出现在初始化列表,那么就会交由编译器处理,一般都是随机值。

初始化列表并不是按照列表的顺序进行初始化,而是按照变量声明的顺序进行初始化。

cpp 复制代码
#include<iostream>
using namespace std;
class A
{
public:

	A(int _a)
	:a(_a)
	,c(a)
	{}
	
	
	int c;
	int a;
};


int main()
{
	A ac(10);
	cout<<ac.a<<endl;
	cout << ac.c;
	return 0;
}

看以上的代码,我先将c先定义,然后再初始化列表中对变量进行赋值,如果看初始化列表的顺序,那么打印结果肯定是两个变量都是10,但是是按照声明顺序,那么结果就是

c是随机值。

隐式类型转换

C++支持内置类型转换为类类型对象,需要有相关内置类型为参数的构造函数。

构造函数前面加explicit关键字就不会再支持隐式类型转换

比如这样的代码就会报错:

cpp 复制代码
#include<iostream>
using namespace std;
class A
{
public:
    //没有定义相关类型参数的构造函数
	int c;
	int a;
};


int main()
{
	A ac=1;//隐式类型转换
	return 0;
}

这样的代码也会报错:

cpp 复制代码
#include<iostream>
using namespace std;
class A
{
public:

	explicit A(int _a)//explicit关键字修饰
	:a(_a)
	,c(a)
	{}
	
	
	int c;
	int a;
};

int main()
{
	A ac=1;
	return 0;
}

static成员

在C++中,静态成员变量需要在类的外部进行初始化,但这一规则有一个例外情况:当静态成员变量被声明为constxepr时,可以在类内部直接初始化。

static成员变量为所有类对象共享,不属于某个具体的对象,因为它并不存在于对象中,存在于静态区中。

static修饰的成员函数(静态成员函数)没有this指针,静态成员函数总可以访问其他的静态成员,但是不能访问非静态的成员,因为没有this指针。

非静态函数可以访问静态变量和静态函数。

突破类域就可以访问静态成员,可以通过类名::静态成员 或者对象.静态成员 访问静态成员变量或者函数。

静态成员也是类的成员,受到publicprivateprotected限制。

静态成员不能在声明位置给缺省值初始化,因为缺省值也是构造函数初始化列表的,静态成员不属于某个对象。

在这里可以用一个代码来统计某个类生成的对象个数。

cpp 复制代码
#include<iostream>
using namespace std;
class A
{
public:
	A()
	{
		count++;
	}
	A(A& a)
	{
		count++;
	}
	~A()
	{
		count--;
	}

	static int count;
};

int A::count = 0;//类外初始化
int main()
{
	A a;
	A b;
	A c(a);
	cout << A::count;//如果是用private修饰的count就不能这么写,需要用额外的函数调用
	return 0;
}

求1+2+3+...+n_牛客题霸_牛客网

cpp 复制代码
class Sum
{
public:
	Sum()
	{
		_ret += _i;
		++_i;
	}
	static int GetRet()
	{
		return _ret;
	}
private:
	static int _i;
	static int _ret;
};
int Sum::_i = 1;
int Sum::_ret = 0;
class Solution {
public:
	int Sum_Solution(int n) {
		Sum arr[n];
		return Sum::GetRet();
	}
};

友元

在类中用private、protected访问限定符修饰的成员是无法访问的,如果用友元(也就是在函数或者类声明前加上friend,并且友元放在类中)突破限制直接访问私有和保护成员。

友元只是一种声明,一个函数可以是多个类的友元。

友元类中的成员函数可以是另一个类的友元函数,都可以访问另一个类中的私有和保护成员。

友元是单向的不相互,A是B的友元但B不是A的友元;并且友元不能传递,A是B的友元,B是C的友元,但A不是C的友元。

注意:友元虽然提供了便利,但是增加了耦合度,破坏封装性,不建议多用。

cpp 复制代码
//由ai生成
#include <iostream>
using namespace std;

class MyClass {
private:
    int secret;

public:
    MyClass(int s) : secret(s) {}

    // 声明友元函数
    friend void revealSecret(MyClass &obj);
};

// 定义友元函数
void revealSecret(MyClass &obj) {
    cout << "The secret is: " << obj.secret << endl;
}

int main() {
    MyClass myObj(42);
    revealSecret(myObj); // 调用友元函数
    return 0;
}
cpp 复制代码
#include<iostream>
using namespace std;
class A
{
private:

	friend void print()
	{
		cout << "a" << "b"<< endl;
	}
	int a, b;
};

class B
{
    friend class A;//友元类
private:
	int a1;
	int a2;
};

内部类

定义在类中的类叫做内部类,但是内部类是独立的一个类,跟全局的类相比,内部类也像个成员一样受到访问限定符的限制。

内部类默认是外部类的友元,比如说class A中定义class B,那么class B默认是class A的友元。

内部类本质也是一种封装,class B(内部类)定义出来主要是给class A(外部类)使用,如果说class A受到private和protected限制,class B只能给class A使用。

求1+2+3+...+n_牛客题霸_牛客网

这道题也可以使用内部类解决:

cpp 复制代码
class Solution {
	// 内部类
	class Sum
	{
	public:
		Sum()
		{
			_ret += _i;
			++_i;
		}
	};
	static int _i; 
	static int _ret;
public:
	int Sum_Solution(int n) {
		Sum arr[n];
		return _ret;
	}
};
int Solution::_i = 1;
int Solution::_ret = 0;

匿名对象

用 类型()定于出来的对象叫匿名对象,相比之前我们定义的对象是有名对象。匿名对象生命周期很短,只有一行,匿名对象只可暂时使用。

cpp 复制代码
#include<iostream>
using namespace std;
class A
{
public:

	void print()
	{
		cout << "a" << "b"<< endl;
	}
	int a, b;
};

int main()
{
	A().print();//使用匿名对象来调用A类中的函数

	return 0;
}

以上是我对C++类和对象的学习,如有错误,欢迎指正。

相关推荐
数据小小爬虫8 分钟前
如何利用Python爬虫获取商品历史价格信息
开发语言·爬虫·python
Gao_xu_sheng10 分钟前
Java程序打包成exe,无Java环境也能运行
java·开发语言
NiNg_1_23416 分钟前
Python的sklearn中的RandomForestRegressor使用详解
开发语言·python·sklearn
谢家小布柔19 分钟前
java中的继承
java·开发语言
黑色叉腰丶大魔王20 分钟前
《基于 Python 的网页爬虫详细教程》
开发语言·爬虫·python
l1384942745125 分钟前
Java每日一题(2)
java·开发语言·游戏
晓纪同学32 分钟前
QT创建一个模板槽和信号刷新UI
开发语言·qt·ui
WANGWUSAN6639 分钟前
Python高频写法总结!
java·linux·开发语言·数据库·经验分享·python·编程
forNoWhat1 小时前
java小知识点:比较器
java·开发语言
坐井观老天1 小时前
在C#中使用资源保存图像和文本和其他数据并在运行时加载
开发语言·c#