类和对象概念
我们编写程序的目的是为了解决现实中的问题,而这些问题的构成都是由各种事物组成,我们在计算机中要解决这种问题,首先要做就是要将这个问题的参与者(事和物)抽象到计算机程序中,也就是用程序语言表示现实的事物。
那么现在问题是如何用程序语言来表示现实事物?现实世界的事物所具有的共性就是每个事物都具有自身的属性和行为,所以如果我们能把事物的属性和行为表示出来,那么就可以抽象出来这个事物。
比如,一个Circle 类,属性包括半径 r,以及方法 getC()、getS(),分别为获取周长和面积。
数据封装和隐藏:
- 把变量(属性)和函数(操作)合成一个整体,封装在一个类中
- 对变量和函数进行访问控制
访问数据成员:类的对象的公共数据成员可以使用直接成员访问运算符 .
来访问。
类的基础代码:
#include <iostream>
using namespace std;
class Fruit{
public:
int price;
void print(){
cout << price << endl;
}
};
int main() {
Fruit apple;
apple.price = 10;
apple.print();
Fruit banana;
banana.price = 20;
banana.print();
return 0;
}
Fruit 只是一个抽象的类,实例化具体对象 apple 和 banana 后才可以进行使用。
类可以理解为一个制造模板的工厂,制造出的具体产品(对象)供人们使用。
访问权限控制
在类的内部(作用域范围内),没有访问权限之分,所有成员可以相互访问。
在类的外部(作用域范围外),访问权限才有意义:public,private,protected。
在类的外部,只有 public 修饰的成员才能被访问,在没有涉及继承与派生时,private 和 protected 是同等级的,外部不允许访问。
class 和 struct 区别:
- struct 默认成员权限 public
- class 默认成员权限 private
#include <iostream>
#include <cstdio>
using namespace std;
const double PI = 3.14;
class Circle{
private:
double m_r;
public:
void setR(double r){
if(r < 0){
cout << "半径赋值不合法" << endl;
m_r = 0;
}
else
m_r = r;
}
double getC(){
return 2 * PI * m_r;
}
double getS(){
return PI * m_r * m_r;
}
};
int main() {
Circle circle;
circle.setR(10);
cout << circle.getC() << endl;
cout << circle.getS() << endl;
return 0;
}
构造函数和析构函数
构造函数函数名和类名相同,没有返回值,不能有 void,但可以有参数。ClassName(){}
析构函数函数名是在类名前面加 ~
组成,没有返回值,不能有 void。不能有参数,不能重载。~ClassName(){}
构造函数分类:
参数类型:分为无参构造函数和有参构造函数
构造分类:普通构造函数和拷贝构造函数
#include <iostream>
#include <cstdio>
#include <string>
using namespace std;
class Person{
private:
string m_name;
int m_age;
public:
Person(){
m_name = "cat";
m_age = 28;
}
/*
Person(string name, int age){
m_name = name;
m_age = age;
}
*/
// 列表初始化
Person(string name, int age) : m_name(name), m_age(age){}
Person(const Person& person){
m_name = person.m_name;
m_age = person.m_age;
}
void print(){
cout << m_name << " " << m_age << endl;
}
};
int main() {
Person blackcat = Person("blackcat", 28);
blackcat.print();
Person blackcat2 = Person(blackcat);
blackcat2.print();
return 0;
}
this指针
指向当前对象的指针。
#include <iostream>
#include <cstdio>
#include <string>
using namespace std;
class Person{
private:
string name;
int age;
public:
Person(){
this->name = "cat";
this->age = 28;
cout << this << endl;
}
Person(string name, int age){
this->name = name;
this->age = age;
cout << this << endl;
}
Person(const Person& person){
this->name = person.name;
this->age = person.age;
}
void print() const {
// this->name = "xxx";
cout << this->name << " " << this->age << endl;
}
};
int main() {
Person cat = Person();
printf("%p\n", &cat);
cat.print();
Person cat2 = Person("cat2", 20);
printf("%p\n", &cat2);
cat2.print();
return 0;
}
继承和派生
面向对象程序设计中最重要的一个概念是继承。继承允许我们依据另一个类来定义一个类,这使得创建和维护一个应用程序变得更容易。这样做,也达到了重用代码功能和提高执行效率的效果。
当创建一个类时,您不需要重新编写新的数据成员和成员函数,只需指定新建的类继承了一个已有的类的成员即可。这个已有的类称为基类,新建的类称为派生类。
当一个类派生自基类,该基类可以被继承为 public、protected 或 private 几种类型。
我们几乎不使用 protected 或 private 继承,通常使用 public 继承。当使用不同类型的继承时,遵循以下几个规则:
- 公有继承(public):当一个类派生自公有基类时,基类的公有成员也是派生类的公有成员,基类的保护成员也是派生类的保护成员,基类的私有成员不能直接被派生类访问,但是可以通过调用基类的公有和保护成员来访问。
- 保护继承(protected): 当一个类派生自保护基类时,基类的公有和保护成员将成为派生类的保护成员。
- 私有继承(private):当一个类派生自私有基类时,基类的公有和保护成员将成为派生类的私有成员。
#include <iostream>
#include <cstdio>
#include <string>
using namespace std;
class Animal{
public:
void eat(){
cout << "我会吃" << endl;
}
void sleep(){
cout << "我会睡" << endl;
}
};
class Dog : public Animal{
public:
void bark(){
cout << "我还会叫" << endl;
}
};
int main() {
Dog dog;
dog.eat();
dog.sleep();
dog.bark();
return 0;
}