C++面向对象的三大特性为:
- 封装
- 继承
- 多态
C++认为万事万物皆为对象,对象有:
- 属性
- 行为
Ex:人可以作为对象,属性有:身高、体重、年龄; 行为有:吃饭、唱歌、睡觉
具有相同性质的对象,我们可以抽象称为类,人属于人类
#include <iostream>
using namespace std;
const double PI = 3.14;
// class代表设计一个类,类名叫:Circle
class Circle
{
public: // 访问权限,公共权限
// 类-1.属性
int r; // 半径
// 类-2.行为(Java中叫方法)
double getPeri() // 获取周长
{
return 2 * PI * r;
}
}; // C++中的类需要加分号,Java中不需要
int main()
{
Circle circle; // C++创建一个圆类的对象
// Java:Circle circle = new Circle();
circle.r = 10;
// 调用行为时即使没有参数,也要带上括号,表明没有参数传入
printf("%.6lf\n", circle.getPeri());
return 0;
}
实例化:通过一个类创建一个对象的过程。
一些术语:
类中的属性和行为统一称为:成员
类中的属性又叫:成员属性 OR 成员变量
类中的行为又叫:成员函数 OR 成员方法
访问修饰符
- public——成员 类中可以访问,类外也可以访问
- protected——成员 类中可以访问,类外不可以访问,儿子可以访问父亲的保护内容
- private——成员 类中可以访问,类外不可以访问,儿子不可以访问父亲的私有内容
#include <iostream>
using namespace std;
class Person {
public:
string name;
protected:
string car;
private:
string password;
public:
void func() {
name = "小白";
car = "拖拉机";
password = "123456";
}
};
int main()
{
Person p1;
p1.name = "小黑";
p1.func();
return 0;
}
struct是自定义的结构体,所以可以让你访问。
但是class类就不同了,它的本意其实并不是让你真正访问里面的数值,而是不让你在意里面的值。
#include <iostream>
using namespace std;
// struct 和 class 的区别
struct C1 {
int n1; // 默认权限是:public
};
class C2 {
int n2; // 默认权限是:private
};
int main()
{
C1 c1;
C2 c2;
printf("%d\n", c1.n1);
printf("%d\n", c2.n2); // err
}
#include <iostream>
using namespace std;
// 静态成员变量
class Person {
public:
// 1.所有对象都共享同一份数据
// 2.在编译阶段就分配内存空间
// 3.类内声明,类外初始化操作
// Q:为什么static要类内声明,而类外初始化呢?
// A:声明并没有开辟内存空间,如果它开辟了内存空间那么在实例化对象时会开辟多次空间
// 所以这是一个保证static成员变量只被定义一次的好方法
static int a; // 只是一个声明,告诉你有一个静态int类型的变量a
};
int Person::a = 100;
int main() {
Person p1;
Person p2;
cout << p1.a << endl;
p1.a = 888;
cout << p2.a << endl;
return 0;
}
静态成员变量不属于某个对象上,所有的对象都共用同一份数据
因此,静态成员变量有两种访问方式:
- 通过对象进行访问
Person p;
cout << p.a << endl; - 通过类名进行访问
cout << Person::a << endl;
#include <iostream>
using namespace std;
class Person
{
public:
static void func() // 静态成员函数
{
cout << "func()函数被调用" << endl;
}
};
int main()
{
// 1.通过对象访问
Person p;
p.func();
// 2.通过类名访问
Person::func();
return 0;
}
#include <iostream>
using namespace std;
class Person
{
public:
static void func() // 静态成员函数
{
cout << "func()函数被调用" << endl;
a = 100; // 静态成员函数可以访问静态成员变量
b = 399; // 静态成员函数不可以访问非静态成员变量,静态成员函数是公共类的,不是私人对象的
}
int b;
static int a;
};
int Person::a = 100;
int main()
{
Person p1, p2;
p1.func();
p2.func();
return 0;
}
#include <iostream>
using namespace std;
class Person
{
};
int main()
{
Person p;
// 空对象占用内存空间为:1
printf("size of p = %d\n", sizeof(p));
return 0;
}
#include <iostream>
using namespace std;
class Person
{
};
int main()
{
Person p;
// 空对象占用内存空间为:1
// C++编译器给每一个空对象分配1个字节的空间,是为了区分每个空对象所占内存的位置
printf("size of p = %d\n", sizeof(p));
return 0;
}
非对象成员变量属于类的对象上
静态成员对象不属于类的对象上
静态/非静态成员函数也不属于类的对象上
#include <iostream>
using namespace std;
class Person // 类名后不要加括号!!!!它不是一个函数
{
public:
int age;
Person(int age) {
// this指针的作用:解决名称冲突
this->age = age; // this指针指向当前的对象
}
};
int main()
{
Person p(18);
printf("%d\n", p.age);
return 0;
}
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class Person
{
public:
// 1.如果在函数的返回值前加const,表示函数的返回值为const,不可修改
// 2.如果在函数体的前面加const,表示this指针是const类型,指针指向的值不可修改
void showPerson() const // 加了这个const,这就是一个常函数了
{
// a = 11123; 等同于下一句代码
// this指针是一个指针常量(指针指向的地址是不可以被修改的)
// this指针指向的地址上的值是可以修改的
// Person* const this = &对象; // 指针常量,指针的指向不可以修改
// const Person* const this = &对象; // 常量指针常量,指针指向的值和指针的指向都不可以修改
this->b = 114514;
}
int a;
// 加了mutable这个关键字,即使是在常函数中,也可以修改这个值
mutable int b; // mut-改变 + able-可...的 -> a.可变的
};
int main()
{
const Person p; // 常对象
// p.a = 10; // 常对象中的属性不能修改
// 常对象只能调用常函数,因为常函数中不能改变属性的值
p.showPerson();
return 0;
}