2.1对象与类

4.1k words

对象与类:通俗版解释


1. 类和对象是什么?

  • :就像一张设计图。比如“汽车设计图”规定了一辆车必须有轮子、发动机、方向盘,还能加速和刹车。
  • 对象:按照设计图造出来的具体东西。比如根据“汽车设计图”造出一辆红色跑车,或者一辆蓝色卡车。

一个类可以创建出多个对象

例子

1
2
3
4
5
6
7
8
9
10
11
12
class Dog {     // 类:狗的“设计图”,通常开头字母大写
public:
string name; // 属性:名字
void bark() { // 方法:叫
cout << "汪汪!";
}
};

Dog myDog; // 对象:按设计图造出一只狗,叫myDog
myDog.name = "旺财"; // 给狗取名
myDog.bark(); // 让狗叫:输出“汪汪!”


2. 类的成员:数据和函数

  • 数据成员:描述对象的属性。比如狗的年龄、颜色。
  • 成员函数:描述对象能做什么。比如狗会叫、会跑。

关键点

  • 数据和方法都写在类里,形成一个整体。
  • 数据一般藏起来(private)方法暴露出去(public)
    → 比如狗的年龄是私有的(不能随便改),但“叫”的方法是公开的(谁都能让狗叫)。

3. 访问控制:public、private、protected

  • public(公开):像房子的门铃,谁都能按。
  • private(私有):像房子的保险箱,只有主人(类内部)能开。不能在类外改,只能在类内使用?修改。
  • protected(保护):像家族保险箱,主人和子女(派生类)能开。

例子

1
2
3
4
5
6
7
8
9
10
class BankAccount {
private:
int balance; // 余额:私有的,不能直接改
public:
void deposit(int money) { // 存钱:公开方法
balance += money;
}
};
// 外部无法直接改balance,只能通过deposit()存钱


4. 对象的创建:直接和间接

  • 直接创建:就像买现成的房子。

    1
    Dog myDog; // 直接定义一个狗对象

  • 间接创建(动态对象):就像租房子,用完了要退租。

    1
    2
    3
    Dog *p = new Dog(); // 租一只狗
    p->bark(); // 让狗叫
    delete p; // 退租(销毁狗)

注意:动态对象必须用new创建,delete销毁,否则会“内存泄漏”(房子不退租,一直占着地皮)。

(attachment:5dc98c3e-8e60-4244-b1b1-8210d8fb0225:image.png)


5. 成员函数:类内和类外实现(二者等价)

  • 类内实现:直接把功能写在设计图里。

    1
    2
    3
    4
    class Dog {
    public:
    void bark() { cout << "汪汪!"; } // 类内实现
    };
  • 类外实现:设计图只写功能名,具体实现写在别处。更常用

    1
    2
    3
    4
    5
    6
    7
    class Dog {
    public:
    void bark(); // 声明
    };
    void **Dog::**bark() { **// 类外实现,加“<类名>::”**
    cout << "汪汪!";
    }

6. 成员对象:对象里的对象(数据成员的类型是类)

  • 一个类可以包含另一个类的对象。比如“汽车类”包含“发动机类”的对象。不能包含该类的对象
1
2
3
4
5
6
7
class Engine { ... };      // 发动机类
class Car {
private:
Engine engine; // 成员对象:汽车的发动机
public:
void start() { engine.ignite(); } // 调用发动机的方法
};

7. 对象的使用:赋值、传参、返回值

  • 赋值:复制数据(比如把A狗的年龄复制给B狗)。同类对象进行赋值默认是把A的数据成员分别赋值给对象B的相应数据成员

  • 传址:

       取对象地址
       Date today;
       Date *p_date;
        p_date = &today; //把对象today的地址赋值给指针p_date
    
  • 传参

    • 传值:复制整个对象(修改不影响原对象)。
    • 传引用:直接操作原对象(修改会影响原对象)。
1
2
3
4
void changeName(Dog d) { d.name = "小黑"; } // 传值:原狗名字不变
**相当于copy了一份,把copy后的对象传给函数,原本对象d不会被函数修改**
void changeNameRef(Dog &d) { d.name = "小黑"; } // 传引用:原狗名字变
**相当于把d直接传给函数,对象d会直接被函数修改**
  • 返回值:可以返回对象(临时副本)或引用(原对象)。


⚠️必考点!!!针对“把对象作为参数传给函数”与“把对象作为函数的返回值”只要有&就直接修改或返回,没有就copy一份再修改或返回

8. 为什么重要?

  • 封装:保护数据(比如不能直接改狗的年龄为负数)。
  • 模块化:每个类独立,方便修改(比如改发动机代码,不影响汽车其他部分)。
  • 复用性:设计图(类)可以反复用,还能继承扩展(比如“警犬类”继承“狗类”)。

总结

  • 是设计图,对象是实物。
  • 数据藏起来方法露出去
  • 动态对象用完要销毁,成员对象随主对象生灭。
  • 传参和返回值要注意是复制还是引用。

就像造车:

  • 设计图(类)规定必须有发动机和方向盘。
  • 造出的车(对象)可以加油、刹车。
  • 发动机(成员对象)藏在车里,不能直接拆。
  • 租车(动态对象)用完要还,否则亏钱!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
using namespace std;
class ju{
private:
int chang;
int kuan;
public:
ju(int a,int b):chang(a),kuan(b){}//如果使用这种初始化方式,则需要在main函数中在一开始定义一个对象的时候就初始化!!!!
int area();
};
int ju::area(){
return chang*kuan;
}
int main(){
ju juu(4,3);**//字符串string要加双引号!!!**
cout<<juu.area();
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
using namespace std;
#include <string>

class Car{
private:
string name;
string madel;
int year;
public:
void inname(string a){
name=a;
} //如果使用这种初始化,需要在main函数中挨个调用这几个初始化函数,不能在定义的时候初始化!!!!
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
const 关键字出现在成员函数的声明中,作用是 指示该成员函数**不会修改类的成员变量**,即它是一个“只读”函数。

具体来说,getSalary() constconst 关键字有以下作用:

**禁止修改类的成员变量**:函数内部不能修改类的非静态成员变量。如果在 getSalary() 函数内部试图修改 salary 或其他成员变量,编译器会报错。

**保证对象的状态不变**:这种做法表明 getSalary() 函数不应该改变调用该函数的对象的状态,因此它可以被调用在 const 对象上(即常量对象)。如果 const 成员函数修改对象状态,编译器会报错。

提升代码可读性和安全性:通过标记为 const,你告诉别人或编译器,函数调用不会有副作用,避免了意外的修改。
#include <iostream>
using namespace std;
class em{
private:
string name;
string ID;
double salary;
public:
em(string a,string b,double c):name(a),ID(b),salary(c){}
void gg(double jixiao){
if(jixiao>=0&&jixiao<+1.4){
salary*=jixiao;
}
else{
cout<<"Your salary enchanged.";
}
}
void sets(double a){
salary=a;
}
string getname()const{
return name;
}
string getID()const{
return ID;
}
double gets()const{
return salary;
}
};
int main(){
em wang("wrf","241220103",30000);
cout<<wang.getname()<<endl;
cout<<wang.getID()<<endl;
cout<<wang.gets()<<endl;
wang.sets(35000);
wang.gg(1.2);
cout<<wang.gets()<<endl;
wang.gg(1.8);
return 0;
}
Comments