目录
构造函数的初始化列表
隐式类型转换
static成员
友元
内部类
匿名对象
构造函数的初始化列表
在之前说过构造函数时,都是在函数体中进行初始化,构造函数也可以在初始化列表中进行对初始化操作,这样就使构造函数看着更加简洁美观。
初始化列表的使用方式是在函数括号的后面加上冒号,用逗号隔开以形成列表,对成员对象进行赋值初始化
在值括号中可放值或者表示式,而每个成员变量在初始化列表中只能出现一次。
在初始化列表中没有出现的成员变量,C++11支持缺省值给那些没出现在初始化列表的变量初始化,如果说某个变量又有缺省值又有初始化列表,那么它的值最终就是初始化列表的值。
引用成员变量、const成员变量、没有默认构造的类类型变量,必须放在初始化列表位置进行赋值,否则会引发编译报错。
成员变量最终都会在初始化列表中进行初始化,如果设置缺省值,才会使用缺省值,但是如果没有缺省值,没有出现在初始化列表,那么就会交由编译器处理,一般都是随机值。
初始化列表并不是按照列表的顺序进行初始化,而是按照变量声明的顺序进行初始化。
#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关键字就不会再支持隐式类型转换
比如这样的代码就会报错:
#include<iostream>
using namespace std;
class A
{
public://没有定义相关类型参数的构造函数int c;int a;
};int main()
{A ac=1;//隐式类型转换return 0;
}
这样的代码也会报错:
#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指针。
非静态函数可以访问静态变量和静态函数。
突破类域就可以访问静态成员,可以通过类名::静态成员 或者对象.静态成员 访问静态成员变量或者函数。
静态成员也是类的成员,受到public、private、protected限制。
静态成员不能在声明位置给缺省值初始化,因为缺省值也是构造函数初始化列表的,静态成员不属于某个对象。
在这里可以用一个代码来统计某个类生成的对象个数。
#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_牛客题霸_牛客网
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的友元。
注意:友元虽然提供了便利,但是增加了耦合度,破坏封装性,不建议多用。
//由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;
}
#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_牛客题霸_牛客网
这道题也可以使用内部类解决:
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;
匿名对象
用 类型()定于出来的对象叫匿名对象,相比之前我们定义的对象是有名对象。匿名对象生命周期很短,只有一行,匿名对象只可暂时使用。
#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++类和对象的学习,如有错误,欢迎指正。