当类里面有其他类成员属性的时候 初始化 先调用其他类构造函数再调用本类构造函数
析构的时候 先调用本类的析构函数 再调用其他类的析构函数。
#include
#include
using namespace std;
class Phone {
private:
string m_name;
public:
Phone(string name): m_name(name){
std::cout << "phoneinit " << std::endl;
}
~Phone() {
std::cout << "~Phone()" << std::endl;
}
};
class People{
private:
string m_name;
Phone1 phone;
public:
//Phone1 phone = phoneName; 隐式转换调用初始化
People(string name, string phoneName):m_name(name),phone(phoneName) {
std::cout << "People1 init " << std::endl;
}
~People() {
std::cout << "~People1()" << std::endl;
}
};
int main(int argc, const char * argv[]) {
// insert code here...
std::cout << "Hello, World!\n";
People p("李四","华为");
std::cout << "end!\n";
return 0;
}
/*
Hello, World!
phone1 init
People1 init
end!
~People1()
~Phone1()
Program ended with exit code: 0
*/
静态成员就是在成员变量和成员函数前加上static 称为静态成员
所有对象共享同一份数据
在编译阶段分配内存
类内声明类外初始化
/// 静态成员变量不归属于某一个对象 所有本类对象 共享
/// 访问 类名访问 或者对象访问
/// 访问权限 私有静态成员变量类外是访问不到的
所有对象共享同一函数
静态成员函数只能访问静态成员变量
#include
#include "mathutil.hpp"
#include
#include "People.hpp"
#include "Phone.hpp"
using namespace std;
class TV{
string m_name;
/// 静态成员变量是有权限的
static string id;
/// 静态方法也是有访问权限的
static void func3() {
}
public:
/// 静态成员变量不归属于某一个对象 所有本类对象 共享
/// 访问 类名访问 或者对象访问
/// 访问权限 私有静态成员变量类外是访问不到的
/// 类内声明
static string color;
static void func() {
/// 静态成员函数可访问静态成员变量 但是不能访问非静态成员变量
/// 静态成员函数也是有访问权限的
std::cout << "func" << "color = " << color <
this指针 指向被调用的成员函数所属的对象
this指针是隐含在每一个非静态成员函数内的一种指针
this指针不需要定义直接使用即可
this指针用途
1.当形参名和成员变量同名时 用this指针调用成员变量做区分
2.在类的非静态成员函数中返回对象本身 可使用 return *this
//类内的成员变量和成员函数分开存储
//只有非静态成员变量才属于类的对象上
#include
#include "mathutil.hpp"
#include
#include "People.hpp"
#include "Phone.hpp"
using namespace std;
//类内的成员变量和成员函数分开存储
//只有非静态成员变量才属于类的对象上
class Person2{
int m_a; /// 非静态成员属于类的对象上
static int m_b; //静态成员变量 不属于类的对象上
void func() {// 非静态成员函数 不属于类的对象上
}
};
int Person2::m_b = 10;
void test36() {
// 空对象占用内存空间为1
// c++ 编译器会给每个空对象也分配一个字节空间 是为了区分空对象占内存的位置
// 每个空对象也应该有一个独一无二的内存地址
std::cout << sizeof(Person2) << std::endl;
Person2 p;
std::cout << sizeof(p) << std::endl;
/*
Hello, World!
1
1
end!
Program ended with exit code: 0
*/
}
int main(int argc, const char * argv[]) {
// insert code here...
std::cout << "Hello, World!\n";
test36();
std::cout << "end!\n";
return 0;
}
this 指针
#include
#include "mathutil.hpp"
#include
#include "People.hpp"
#include "Phone.hpp"
using namespace std;
class Person3{
public:
int age;
Person3(int age){
// this 指针指向的是被调用的成员函数所属的对象 也就是属于当前对象
this->age = age;
}
/// 链式调用
Person3& changeAge(int num) {
this->age = this->age + num;
return *this;
}
};
void test37() {
Person3 p(21);
p.changeAge(12).changeAge(12).changeAge(12);
std::cout << p.age;
}
int main(int argc, const char * argv[]) {
// insert code here...
std::cout << "Hello, World!\n";
test37();
std::cout << "end!\n";
return 0;
}
空指针
class Person3{
public:
int age;
Person3(int age){
// this 指针指向的是被调用的成员函数所属的对象 也就是属于当前对象
this->age = age;
}
/// 链式调用
Person3& changeAge(int num) {
this->age = this->age + num;
return *this;
}
void info() {
if (this == nullptr) {
return;
}
std::cout << this->age << std::endl;
}
};
void test37() {
Person3 *p1 = NULL;
p1->info();
Person3 p(21);
p.changeAge(12).changeAge(12).changeAge(12);
std::cout << p.age;
}
成员函数后加const后我们称这个函数为常函数。
常函数内不可以 修改成员属性。
成员属性声明时加关键字mutable后 在常函数中依然可以修改
声明对像前加const称该对象为常对象
常对象只能调用常函数
#include
#include
using namespace std;
class Person4{
public:
int m_A;
mutable int m_B;
Person4(int a,int b){
m_A = a;
m_B = b;
}
// this 指针的本质 是指针常量 指针的指向是不可以修改的
// 在成员函数后加const 修饰的是 this指针 让指针指向的值不可以修改 const Person4* const this
void showPerson() const{
//this = nullptr; //Expression is not assignable this指针的指向是不可以修改的
//this -> m_A = 10;//Cannot assign to non-static data member within const member function 'showPerson'
}
void changeValue() const {
this->m_B = 20;
//this->m_A = 10;//Cannot assign to non-static data member within const member function 'changeValue'
}
void func() {
}
};
void test38() {
const Person4 p(2,5); //常对象
//p1.m_A = 100; 常对象不 能访问非常变量
p.m_B = 100;//常对象只能访问常变量
p.changeValue();
//p.func(); // 常对象不能调用非常函数
}
int main(int argc, const char * argv[]) {
// insert code here...
std::cout << "Hello, World!\n";
test38();
std::cout << "end!\n";
return 0;
}
#include
using namespace std;
class A {
// 友元函数可以访问类的私有属性或者方法
friend void changeAPrivateValue(A &a);
private:
int m_a;
void func() {
std::cout << "func" << std::endl;
}
public:void changeAPrivateValue(A &a);
A(int a,int b):m_a(a),m_b(b){
}
int m_b;
};
void changeAPrivateValue(A &a) {
a.func();
std::cout << a.m_a << std::endl;
}
int main(int argc, const char * argv[]) {
// insert code here...
std::cout << "Hello, World!\n";
A a(11,33);
changeAPrivateValue(a);
std::cout << "end!\n";
return 0;
}
#include
#include "mathutil.hpp"
#include
#include "People.hpp"
#include "Phone.hpp"
using namespace std;
// 友元类
class BClass;
class C {
public:
void visit();
BClass *m_b;
C();
};
class BClass{
/// 友元类
friend class C;
private:
int m_a;
void func(){
std::cout << "fuc" << std::endl;
}
public:
BClass();
int m_b;
void func2() {
std::cout << "fuc2" << std::endl;
}
};
// 成员函数放类外
BClass::BClass() {
}
C::C() {
m_b = new BClass;
}
void C::visit() {
m_b->m_b = 10;
m_b -> m_a = 33;
std::cout << m_b->m_b << std::endl;
std::cout << m_b -> m_a << std::endl;
}
int main(int argc, const char * argv[]) {
// insert code here...
std::cout << "Hello, World!\n";
C c;
c.visit();
std::cout << "end!\n";
return 0;
}
#include
#include
using namespace std;
class EClass;
class DClass {
public:
DClass();
EClass *eclass;
void visit();
void visit2();
};
class EClass {
///告诉编译器DClass 类的visit2 作为你本类的 友元函数 可以访问本类的 私有成员
friend void DClass::visit2();
private:
int m_a;
public:
EClass();
int m_b;
};
EClass :: EClass() {
m_a = 20;
m_b = 30;
}
DClass:: DClass() {
eclass = new EClass;
}
void DClass:: visit() {
std::cout << eclass->m_b << std::endl;
// 不能访问私有成员
}
void DClass:: visit2() {
// 能访问私有成员也能访问非私有成员
std::cout << eclass->m_b << std::endl;
std::cout << eclass->m_a << std::endl;
}
int main(int argc, const char * argv[]) {
// insert code here...
std::cout << "Hello, World!\n";
DClass dclass;
dclass.visit();
dclass.visit2();
std::cout << "end!\n";
return 0;
}