2026《数据结构》考研复习笔记二(C++面向对象)

发布于:2025-04-18 ⋅ 阅读:(24) ⋅ 点赞:(0)

一、类

1.1类&对象

class classname//class是关键词,classname是类名
{
Access specifiers://访问修饰符:private/public/protected
Date members/variables;//变量
Member functions(){}//方法
}//分号结束一个类

【例】定义Box类

class Box//盒子 
 
private: 
double length;//长 
double breadth;//宽 
double height;//高 
 
//成员函数声明   
public:  
tuple< double,double,double>GetMessage();//获取盒子信息 
void set(double len,double bre,double hei);//修改盒子信息 
} 
}; 
 
tuple< double,double,double> Box::GetMessage(){
return {length,breadth,height}; 
} 
 
void Box::set(double len,double bre,double hei){ 
length=len; 
breadth=bre;  
height=hei; 
} 
 
访问类的成员函数: 
Box Box1; 
Box1.GetMessage();//此处有省略,应当有构造函数,下面介绍
 

1.2类成员函数

成员函数的作用:
类的成员函数只属于该类,是类的一个成员,它可以访问类的成员,对具体的对象进行操作(private修饰的成员变量只能由成员函数进行修改)

成员函数的定义:
成员函数可以定义在类定义内部,或单独使用范围解析运算符::定义
如:

tuple< double,double,double> Box::GetMessage(){
return {length,breadth,height};

1.3类访问修饰符

public成员:在类的外部可以访问,不需要通过成员函数设置和获取共有变量的值

private成员:在类的外部不可访问,只有该类和友元函数可以访问私有成员

protected成员:与private成员相似,但是protected成员可以在派生类(子类)中访问

三种继承方式:
public继承:基类public成员、protected成员、private成员的访问属性在派生类中分别变成了public,protected,private
protected继承:基类public成员、protected成员、private成员的访问属性在派生类中分别变成了protected,protected,private
private继承:基类public成员、protected成员、private成员的访问属性在派生类中分别变成了private,private,private

1.4构造函数&析构函数

#include< iostream> 
using namespace std; 
 
class Line 
{ 
public: 
void setLength(double len); 
double getLength(void); 
Line();//不带参数的构造函数 
Line(double len);//带参数的构造函数 
~Line();//析构函数 
 
private: 
double length; 
}; 
 
Line::Line(void){ 
cout<<"Object is being create"<< endl; 
} 
 
Line::Line(double len){ 
cout<<"Object is being create,length= "<< len<< endl; 
} 
 
Line::~Line(void){ 
cout<<"Object is being deleted"<< endl; 
} 
 
void Line::setLength(double len){ 
length=len; 
} 
 
double Line::getLength(void){ 
return length; 
} 
 
int main(){ 
Line line; 
line.setLength(6.0); 
cout<<"Length of line : "<< line.getLength()<< endl; 
return 0; 
} 
 
//编译上述代码并执行产生下面结果: 
//Object is being created 
//Length of line : 6 
//Object is being deleted

1.5拷贝构造函数
拷贝构造函数属于构造函数,如果类带有指针变量并有动态内存分配,它在创建对象时,使用同一类中之前创建的对象来初始化新创建的对象。通常用于:

  • 同一个同类型的对象初始化新对象(=赋值)
  • 复制对象把它作为参数传递给函数
  • 复制对象,并从函数返回这个对象

常见形式:
classname (const classname &obj){……}//obj是一个对象的引用,用于初始化另一个对象

【例】拷贝构造函数——此处省略class的其他函数,只展示拷贝构造函数的定义以及用法

Line::Line(const Line &obj)
{
    cout << "调用拷贝构造函数并为指针 ptr 分配内存" << endl;
    ptr = new int;
    *ptr = *obj.ptr; // 拷贝值
}
// 程序的主函数
int main( )
{
   Line line(10);
   Line line2=line1;
   print(line);
 
   return 0;
}

1.6友元函数
类的友元函数在类的定义中声明,但不是成员函数。友元函数定义在类外部,有权访问类的所有private成员和protected成员。

友元可以是函数(友元函数),也可以是类(友元类)
如:
friend void printWidth(Box box);
friend class ClassTwo;

【例】友元函数

class Box
{
   double width;
public:
   friend void printWidth( Box box );
   void setWidth( double wid );
};
// 请注意:printWidth() 不是任何类的成员函数
void printWidth( Box box )
{
   /* 因为 printWidth() 是 Box 的友元,它可以直接访问该类的任何成员 */
   cout << "Width of box : " << box.width <<endl;
}
printWidth( box );

1.7内联函数
函数名前有关键字inline的函数为内联函数,内联函数在编译时,编辑器会把该函数的代码副本放置在每个调用该函数的地方。类定义中定义的函数都是内联函数

1.8this指针
this是一个隐藏的指针,可以在类的成员函数中使用,用来指向当前调用对象(当一个对象的成员函数被调用时,编辑器会隐式地传递该对象的地址作为this指针)。友元函数没有this指针,因为友元不是类的成员,只有成员函数才有this指针

例如:

int compare(Box box)
      {
         return this->Volume() > box.Volume();
      }
 Box1.compare(Box2);

1.9指向类的指针
一个指向 C++ 类的指针与指向结构的指针类似,访问指向类的指针的成员,需要使用成员访问运算符 ->

常见操作:

1. MyClass obj;
   MyClass *ptr=&obj;//指向对象
2. MyClass *ptr=new MyClass;//动态分配
3. void processObject(MyClass *ptr){ptr->display():}//作为函数参数传递

1.10类的静态对象
使用static关键字把类成员定义为静态时,无论创建多少个类的对象,静态成员变量只有一个副本(静态成员在类的所有对象中是共享的)。不能把静态成员变量的初始化放置在类的定义中,但是可以在类的外部通过使用范围解析运算符::重新声明静态变量从而对它进行初始化

静态成员函数即使在类对象不存在的情况下也能被调用,静态函数只要使用类名加范围解析运算符 :: 就可以访问。

静态成员函数没有this指针,只能访问静态成员(包含静态成员变量和静态成员函数)。静态函数即使在类对象不存在的情况下也能被调用,只要使用classname::即可访问

练习实例——点击跳转(笔者本人应用知识点写的代码)

二、继承

2.1派生类
基本形式:class derived_class:access_specifier base_class。其中derived_class是派生类名,access_specifier 是public\protected\private中的一个,base_class是基类名。例如:class Dog:public Animal{};

// 基类 
class Shape  { 
   protected: 
      int width; 
      int height; 
}; 
  
// 派生类 
class Rectangle: public Shape { 
   public: 
      int getArea() {  
         return (width * height);  
      } 
}; 

派生类可以访问基类中所有的非私有成员。因此基类成员如果不想被派生类的成员函数访问,则应在基类中声明为 private。

2.2多继承
class <派生类名>:<继承方式1><基类名1>,<继承方式2><基类名2>,…{
<派生类类体>
};

class A: public B, public C{……}

三、重载运算符和重载函数

C++允许在同一个作用域中函数和运算符有多个定义(参数列表不同)——函数重载运算符重载

3.1函数重载
重载的同名函数形参必须不同(参数的个数、类型或者顺序)。如:

void print(int i) {
        cout << "整数为: " << i << endl;
      }
void print(double  f) {
        cout << "浮点数为: " << f << endl;
      }
void print(char c[]) {
        cout << "字符串为: " << c << endl;
      }

3.2运算符重载
基本形式:< return > operator < op>(parameter)

点击运算符可查看重载代码

一元运算符 递增运算符++,递减运算符--,负号-,逻辑非!
二元运算符 加+,减-,乘*,除/
关系运算符 < , > , <= , >= , ==
输入/输出运算符 << , >>
赋值运算符 =
函数调用运算符 ()
下标运算符 []
类成员访问运算符 ->

四、多态

4.1虚函数

  • 在基类声明一个虚函数(关键字为virtual)
  • 派生类可以重写虚函数
  • 调用虚函数时,会根据对象的实际类型决定调用哪个版本的函数
class Animal {
public:
    virtual void sound() {  // 虚函数
        cout << "Animal makes a sound" << endl;
    }
};

class Dog : public Animal {
public:
    void sound() override {  // 重写虚函数
        cout << "Dog barks" << endl;
    }
};

4.2动态绑定

  • 在运行时决定函数调用的具体实现
  • 需要使用指向基类的指针或引用来调用虚函数,运行时根据对象的类型决定调用哪个函数
Animal *animal = new Dog();
    animal->sound();  // 输出: Dog barks

4.3纯虚函数
当想要在基类中定义虚函数,但又不能对虚函数给出有意义的实现,这是会用到纯虚函数

  • 一个包含纯虚函数的类被称为抽象类,不能被直接实例化
  • 纯虚函数没有函数体 ,声明时使用=0
  • 强制派生类提供具体的实现
class Shape {
public:
    virtual int area() = 0;  // 纯虚函数,强制子类实现此方法
};
 
class Rectangle : public Shape {
private:
    int width, height;
public:
    Rectangle(int w, int h) : width(w), height(h) { }
    
    int area() override {  // 实现纯虚函数
        return width * height;
    }
};

4.4多态的实现机制

  • 虚函数表:C++运行时使用虚函数表来实现多态,每个包含虚函数的类都有一个虚函数表,表中存储了指向类中所有虚函数的指针

本节实例处

代码示例


”类“练习代码

#include<iostream>
#include<tuple>
using namespace std;


class Box {
private:
	int hei;
	int len;
	int bre;
	Box* next;
	static int num;
public:
	Box();//不带参数的构造函数
	Box(int hei, int len, int bre, Box* next = NULL);//带参数的构造函数
	Box(const Box& box);//拷贝构造函数(浅拷贝&深拷贝)
	~Box();//析构函数
	void set(int hei, int len, int bre, Box* next = NULL);
	tuple<int, int, int, Box*>GetMessage();
	int Volume();

	friend void print(const Box& box);
};

int Box::num = 0;//初始化静态变量



int main() {
	Box box(1, 1, 1);
	cout << "box的体积为" << box.Volume() << endl;
	print(box);
	return 0;
}


Box::Box():hei(0),len(0),bre(0),next(NULL) {
	num++;
	cout << "Block box is being created" << endl;
}

Box::Box(int hei, int len, int bre, Box* next) :hei(hei), len(len), bre(bre), next(next) {
	num++;
	cout << "A box is being created, whose hei is " << hei << " ,len is " << len << " and bre is " << bre << endl;
}

Box::Box(const Box& box) {
	num++;
	hei = box.hei;
	len = box.len;
	bre = box.bre;
	next = new Box;
	*next = *box.next;
	cout << "A box is being created, whose hei is " << hei << " ,len is " << len << " and bre is " << bre << endl;
}

Box::~Box() {
	cout << "A box is being deleted, whose hei is " << hei << " ,len is " << len << " and bre is " << bre << endl;
}

void Box::set(int hei, int len, int bre, Box* next) {
	this->hei = hei;
	this->len = len;
	this->bre = bre;
	this->next = next;
}

tuple<int, int, int, Box*> Box::GetMessage() {
	return { hei,len,bre ,next };
}

int Box::Volume() {
	return hei * len * bre;
}

void print(const Box& box) {
	cout << "This box message is :" << "height(" << box.hei << ")" << " " << "length(" << box.len << ")" << " " << "breadth(" << box.bre << ")" << endl;
}

跳转返回——继承

成员函数:ReturnType operator-() const{……}
全局函数:ReturnType operator-(const ClassType&obj){……}


递增运算符++
前置递增++obj重载(成员函数)

class Counter {
private:
    int count;
public:
    Counter(int c = 0) : count(c) {}

    // 前置递增 ++obj
    Counter& operator++() {
        ++count;       // 先递增
        return *this;  // 返回当前对象的引用
    }

    int getCount() const { return count; }
};

int main() {
    Counter c(5);
    ++c;  // 调用 operator++()
    std::cout << c.getCount();  // 输出 6
}

前置递增++obj重载(全局函数)

class Counter {
private:
    int count;
public:
    Counter(int c = 0) : count(c) {}
    friend Counter& operator++(Counter& c);  // 声明友元
    int getCount() const { return count; }
};

// 全局前置 ++
Counter& operator++(Counter& c) {
    ++c.count;
    return c;
}

后置递增obj++重载(成员函数)

class Counter {
private:
    int count;
public:
    Counter(int c = 0) : count(c) {}

    // 后置递增 obj++
    Counter operator++(int) {//int是占位参数,用于区分前置和后置
        Counter temp = *this;  // 保存当前值
        ++count;               // 递增
        return temp;           // 返回旧值
    }

    int getCount() const { return count; }
};

int main() {
    Counter c(5);
    Counter old = c++;  // 调用 operator++(int)
    std::cout << old.getCount();  // 输出 5(旧值)
    std::cout << c.getCount();    // 输出 6(新值)
}

后置递增obj++重载(全局函数)

class Counter {
private:
    int count;
public:
    Counter(int c = 0) : count(c) {}
    friend Counter operator++(Counter& c, int);  // 声明友元
    int getCount() const { return count; }
};

// 全局后置 ++
Counter operator++(Counter& c, int) {
    Counter temp = c;
    ++c.count;
    return temp;
}

跳转返回——多态

负号-
成员函数重载:

   class Number {
private:
    int value;
public:
    Number(int v) : value(v) {}
    
    // 一元减运算符重载(成员函数)
    Number operator-() const {
        return Number(-value);
    }
    
    int getValue() const { return value; }
};

int main() {
    Number n(5);
    Number neg = -n;  // 调用重载的一元减运算符
    std::cout << neg.getValue();  // 输出 -5
}

全局函数重载:

class Number {
private:
    int value;
public:
    Number(int v) : value(v) {}
    int getValue() const { return value; }
};

// 一元减运算符重载(非成员函数)
Number operator-(const Number& num) {
    return Number(-num.getValue());
}

int main() {
    Number n(10);
    Number neg = -n;  // 调用重载的一元减运算符
    std::cout << neg.getValue();  // 输出 -10
}

跳转返回——多态

加+
成员函数重载

class Box {
private:
    int hei, len, bre;
public:
    // ...(其他成员函数和构造函数)

    // 成员函数重载 +
    Box operator+(const Box& other) const {
        return Box(
            hei + other.hei,  // 高度相加
            len + other.len,  // 长度相加
            bre + other.bre   // 宽度相加
        );
    }
};

全局函数重载

class Box {
private:
    int hei, len, bre;
public:
    // ...(构造函数和其他成员函数)
    
    // 声明友元,让全局函数能访问私有成员
    friend Box operator+(const Box& lhs, const Box& rhs);
};

// 全局函数重载 +
Box operator+(const Box& lhs, const Box& rhs) {
    return Box(
        lhs.hei + rhs.hei,
        lhs.len + rhs.len,
        lhs.bre + rhs.bre
    );
}

跳转返回——多态

等于==
成员函数

class Box {
private:
    int hei, len, bre;
public:
    // ...(其他成员函数和构造函数)

    // 成员函数重载 ==
    bool operator==(const Box& other) const {
        return (hei == other.hei) && 
               (len == other.len) && 
               (bre == other.bre);
    }
};

全局函数

class Box {
private:
    int hei, len, bre;
public:
    // ...(构造函数和其他成员函数)
    
    // 声明友元,让全局函数能访问私有成员
    friend bool operator==(const Box& lhs, const Box& rhs);
};

// 全局函数重载 ==
bool operator==(const Box& lhs, const Box& rhs) {
    return (lhs.hei == rhs.hei) && 
           (lhs.len == rhs.len) && 
           (lhs.bre == rhs.bre);
}

跳转返回——多态

输入>>
全局函数

#include <iostream>
using namespace std;

class Box {
private:
    int hei, len, bre;
public:
    // 声明友元函数,允许访问私有成员
    friend istream& operator>>(istream& is, Box& box);
};

// 全局函数重载 >>
istream& operator>>(istream& is, Box& box) {
    is >> box.hei >> box.len >> box.bre;  // 按顺序读取长、宽、高
    return is;  // 返回输入流以支持链式调用(如 cin >> box1 >> box2)
}

跳转返回——多态

赋值=

class Box {
private:
    int hei, len, bre;
    Box* next;  // 假设包含动态分配的资源
public:
    // ...(其他成员函数和构造函数)

    // 重载赋值运算符 =
    Box& operator=(const Box& other) {
        if (this != &other) {  // 防止自赋值(如 a = a)
            hei = other.hei;
            len = other.len;
            bre = other.bre;

            // 深拷贝 next(如果存在)
            if (next != nullptr) {
                delete next;  // 释放原有资源
                next = nullptr;
            }
            if (other.next != nullptr) {
                next = new Box(*other.next);  // 深拷贝
            }
        }
        return *this;  // 返回当前对象的引用
    }
};

跳转返回——多态

函数调用运算符()

#include <iostream>
using namespace std;

class Adder {
    int value;
public:
    Adder(int v) : value(v) {}
    
    // 重载函数调用运算符
    int operator()(int x) {
        return value + x;
    }
};

int main() {
    Adder add5(5);  // 创建一个Adder对象,初始值为5
    
    cout << add5(10) << endl;  // 像函数一样调用,输出15
    cout << add5(20) << endl;  // 输出25
    
    return 0;
}

跳转返回——多态

下标运算符[]

#include <iostream>
#include <vector>
using namespace std;

class IntArray {
    vector<int> data;
public:
    IntArray(size_t size) : data(size) {}
    
    // 非常量版本,允许修改
    int& operator[](size_t index) {
        if (index >= data.size()) {
            throw out_of_range("Index out of range");
        }
        return data[index];
    }
    
    // 常量版本,只读访问
    const int& operator[](size_t index) const {
        if (index >= data.size()) {
            throw out_of_range("Index out of range");
        }
        return data[index];
    }
    
    size_t size() const { return data.size(); }
};

int main() {
    IntArray arr(5);
    
    // 使用[]赋值
    for (size_t i = 0; i < arr.size(); ++i) {
        arr[i] = i * 10;
    }
    
    // 使用[]读取
    for (size_t i = 0; i < arr.size(); ++i) {
        cout << arr[i] << " ";
    }
    // 输出: 0 10 20 30 40
    
    // 常量对象使用
    const IntArray carr(3);
    cout << carr[0];  // 使用const版本
    
    return 0;
}

跳转返回——多态

类成员访问运算符->

#include <iostream>
using namespace std;

class Data {
public:
    int value;
    Data(int v) : value(v) {}
    void print() { cout << "Value: " << value << endl; }
};

class DataPtr {
    Data* ptr;
public:
    DataPtr(Data* p) : ptr(p) {}
    ~DataPtr() { delete ptr; }
    
    // 重载->运算符
    Data* operator->() { return ptr; }
    const Data* operator->() const { return ptr; }
};

int main() {
    DataPtr dp(new Data(42));
    
    dp->print();       // 实际调用: dp.operator->()->print()
    dp->value = 100;   // 访问成员变量
    
    const DataPtr cdp(new Data(200));
    cdp->print();      // 使用const版本
    
    return 0;
}

跳转返回——多态


多态实例

#include <iostream>
using namespace std;
 
// 基类 Shape,表示形状
class Shape {
   protected:
      int width, height; // 宽度和高度
 
   public:
      // 构造函数,带有默认参数
      Shape(int a = 0, int b = 0) : width(a), height(b) { }
 
      // 虚函数 area,用于计算面积
      // 使用 virtual 关键字,实现多态
      virtual int area() {
         cout << "Shape class area: " << endl;
         return 0;
      }
};
 
// 派生类 Rectangle,表示矩形
class Rectangle : public Shape {
   public:
      // 构造函数,使用基类构造函数初始化 width 和 height
      Rectangle(int a = 0, int b = 0) : Shape(a, b) { }
 
      // 重写 area 函数,计算矩形面积
      int area() override { 
         cout << "Rectangle class area: " << endl;
         return width * height;
      }
};
 
// 派生类 Triangle,表示三角形
class Triangle : public Shape {
   public:
      // 构造函数,使用基类构造函数初始化 width 和 height
      Triangle(int a = 0, int b = 0) : Shape(a, b) { }
 
      // 重写 area 函数,计算三角形面积
      int area() override { 
         cout << "Triangle class area: " << endl;
         return (width * height / 2); 
      }
};
 
// 主函数
int main() {
   Shape *shape;           // 基类指针
   Rectangle rec(10, 7);   // 矩形对象
   Triangle tri(10, 5);    // 三角形对象
 
   // 将基类指针指向矩形对象,并调用 area 函数
   shape = &rec;
   cout << "Rectangle Area: " << shape->area() << endl;
 
   // 将基类指针指向三角形对象,并调用 area 函数
   shape = &tri;
   cout << "Triangle Area: " << shape->area() << endl;
 
   return 0;
}

网站公告

今日签到

点亮在社区的每一天
去签到