set()与get()方法class Person
{
//私有访问权限
private:
string name;
int age;
//公有访问权限
public:
void work()
{
cout << "正在努力的工作" << endl;
}
string getName() // 获取
{
return name;
}
void setName(string _name) // 设置
{
this->name = _name;
}
};
int main()
{
Person p; //在栈区使用Person类定义对象
Person* pa = new Person; //在堆区使用Person类定义对象。
pa->setName("zhangsan"); // 设置
pa->work(); // 正在努力的工作
cout << pa->getName() << endl; // 获取
delete pa;
return 0;
}
class 定义的的类与C中字节对齐是一致的。类中的成员函数并不占用类或对象的空间。
class A
{
public: // 属性才占用空间
int a; // 4字节 只有int a时 sizeof (A)=4
double b; // 8 字节 sizeof (A)=16
void show() // 不占用空间 ;
{
cout << "hello" << endl;
}
};
static修饰的静态成员函数中不可以使用this指针(没有this)可以使用this指针 --> 类中static修饰的变量 class Stu
{
private:
string name;
public:
//返回本对象。
Stu& setName(const string& name)
{
this->name = name;
//返回本对象
return *this; // 指针指向Stu
}
};
class A{
int* p;
public:
A( ) = default;// 构造函数 ,默认构造
A()
{
this->p = new int[1024];
} // 构造函数
~A()
{
delete []p;
} // 析构函数
};
返回值,连void都没有。参数类型与个数不同形成重载关系。没有定义任何 自定义的构造函数,编译器就会的提供一个默认的构造函数。有提供任何一个自定义的构造函数,编译器就不再提供任何默认的构造函数。一个类中可以有多个构造函数,只能有一个析构函数 (堆区空间不能多次释放)A a2 = 10; 隐式调用
A a2(20); 显式调用 用意:提高代码的可读性,维护。
class A
{
int num;
public:
A()
{
cout << "A()" << endl;
}
// 必须显式调用
explicit A(int _num) //指定编译器调用此构造时,必须显式调用。用意:提高代码的可读性,维护。
{
this->num = _num;
}
};
int main()
{
A a; //调用的无参空构造
A a1(10); //调用的有参的构造
A a2 = 10; //隐式调用。
// 以下 都是 显式调用
A a2(20);
A* pa = new A;
A* pa1 = new A();
return 0;
}
类中有const修饰的类型变量时,使用初始化列表来进行初始化。
构造函数的初始化列表是构造函数的特殊语法,所以只在构造函数中使用
构造函数的(): 类中属性变量(初值),类中属性变量2(),...
初始化列表的初始化的顺序:按照类中属性声明的顺序依次进行初始化。
初始化列表的调用时机:开辟空间之后,编译器调用的初始化列表,然后再调用的构造函数。
类中 定义其他类对象 需要 在初始化列表中初始化
class B
{
public: // 公有
int number;
public: // 公有
explicit B(int _number) //explicit关键字 显式调用指定
{
this->number = _number;
}
};
class A
{
public: // 公有
const int number;
const int age;
int efg;
string name; // 可以初始化,也 可以不初始化
B b; // 类 定义对象 要在初始化列表中,初始化
public: // 公有
A():number(10),age(88),name("zhansan"),b(B(10)) // 初始化列表方式及初始化顺序
{
cout << "A的无参空构造" << endl;
}
A(int a, int b):number(10),age(88),name("zhansan"),b(B(10))
{
efg = b;
}
};
int main()
{
A a;
A a1(15,16);
return 0;
}
static修饰的成员变量,系统会为进程分配一个0-4G的内存空间
**文件代码段:**编译好的机器码,内容即是 一个个函数机器码 及 保存函数地址的指针。
rodata段:即全局只读数据,比如:全局const修饰的变量或字符串。
data段: 已初始化的全局变量或static修饰且初始化的变量。
(data段数据 将 在程序执行前 系统调用copy_data()函数 向程序中拷贝一分副本)
bss段: 未被初始化的全局变量,或局部定义使用static 修饰的静态变量。
(bss段数据 在程序执行前 系统会调用bss_clear()函数 对其进行初始化)
当用static在类中修饰一个成员变量时,由于类中定义的static是隐藏在类中,系统无法调用bss_clear()直接进行初始化。
必须要在类外对static修饰的成员变量进行首次初始化。 class Stu
{
private:
string name;
public:
static int count; // static修饰的变量,只生成一份。因为他在静态区,进程空间对静态区只开辟一次。
// 而且这一份静态空间 是所有使用Stu类的对象的共享的一份。
// static修饰的变量或对象,是属于整个进程的,只不过是隐藏在了类域之中。
// 所以需要在类外的 全局区 进行初始化。
//所以static修饰的变量或对象,是属于整个类的,可以使用类名 : : 的方式直接访问。
Stu() = default;//默认构造
Stu(string name)
{
this->name = name;
this->count++; //记录count的值。
}
};
//static 修饰的类中的属性的初始化的语法格式。
int Stu::count = 0;
由于,静态区数据只会由进程加载一次,在静态区的类成员数据,是所有对象的共享部分。
也就是所有对象都共享这份数据,当这份数据被修改时,所有对象中的这分共享部分都将被修改。
由于静态成员变量定义在静态区内存,而对象(类)是存在于动态区之中,所以静态成员变量并不占用类对象的内存空间。
由于类中静态成员变量,是属于整个进程的,进程执行前就已经在静态区存储,而类对象是在动态区的,所以此成员不依赖于某个类对象的,它是属于整个进程的,
因为他又隐藏于类中,所以我们可以使用 类域访问 的形式对直接访问。(等于有 类内的访问权限的限制。)
类名 ::静态成员函数
static修饰的成员函数称为静态成员函数。static修饰的成员变量,称为静态成员变量。
普通成员函数 是 可以调用 类中的静态成员变量。
普通成员对象 是 可以调用 类中的静态成员函数。
但是static修饰的成员函数是不可以访问类中的非静态属性的。因为它 没有this指针。只能访问类中的 静态属性。
static修饰的变量,是服务于整个类,static修饰的成员函数,也是服务于整个类的
底层逻辑:
使用static修饰成员函数与修饰变量不同,并不是对存储方式的修饰,而是将此成员函数提升为全局函数的特性。由于全局函数中的形参是定义在全局数据段的,所以没有this指针,所以是没有办法调用到类中的成员的。所以类中的静态成员函数是 不可访问普通成员变量或函数的。
普通成员对象或函数 是 可以访问 静态成员变量或调用静态函数的
static int count; // 静态成员变量, 在静态区, 需要在类外的 全局区 进行初始化
static int getCount() // 静态成员函数, 成员函数提升为全局函数;没有this指针,
{
return count;
}
//这就是静态函数的意义向在。无需依赖于某一个对象。 类名 :: 全局函数
cout << Stu::getCount() << endl;
常对象,不可以调用类中的普通成员函数,常对象 只能调用 常函数。因为类中的普通成员函数是有this指针,通过this指针是调用或修改类中的属性的,程序设计的安全性,常对象 只能调用 常函数。普通对象是可以调用常函数的。常函数 中是 不可以 对类中的属性进行 写操作,只能 读操作。 void setName(string name) // 类中 普通成员函数
{
this->name = name;
}
string getName( )const //类中 常函数
{
//this->name = "gaowanxi"; //const修饰的函数是不可以对类内属性进行 写操作的。
return this->name;
}
// 常对象
void showInfo(const Stu stu)
{
//stu.setName("zhangshan"); // 常对象是不可调 用类中的成员函数的。
cout << stu.getName() << endl; //常对象 只能调用 常函数。
}