C++ 抽象

一,纯虚函数:没有函数体的虚函数

abstract_base.h

/**
 * C++中的纯虚函数(或抽象函数)是我们没有实现的虚函数!我们只需声明它!通过声明中赋值0来声明纯虚函数!
 * 纯虚函数:没有函数体的虚函数
*/

/**
 * 抽象类
*/
class AbstractBase {
    public:
    // 纯虚函数
    virtual void show() = 0;
}

abstract.cpp

#include <iostream>
using namespace std;

class A {
    public:
    virtual void f() = 0; //纯虚函数
    void g() { this-> f(); }
    A() {}
};

class B: public A {
    public:
    // 实现父类A中的虚函数
    void f() {
        cout << "B:f()" << endl;
    }
};

int main() {
    B b;
    b.g();
    return 0;
}

编译运行

二,抽象类由派生类集成实现!

derived_full.cpp

/**
 * 抽象类由派生类集成实现!
*/

#include <iostream>
using namespace std;

class Base {
    int x;

    public:
        virtual void fun() = 0;
        int getX() {return x;}
};

class Derived : public Base {
    public:
        void fun() {cout << "fun() called" << endl; } //实现fun()函数
};

int main(void) {
    Derived d;
    d.fun(); // 不是new出来的,用.
    return 0;
}

三,抽象类可以有构造函数

interesting_facts1.cpp

/**
 * 纯虚函数使一个类变成抽象类
*/

#include <iostream>
using namespace std;

/**
 * 抽象类至少包含一个纯虚函数
*/
class Test {
    int x;

public:
    virtual void show() = 0;
    int getX() {return x;}
};

int main(void) {
    Test t; // error!不能创建抽象类的对象
    return 0;
}

四, 抽象类类型的指针和引用

interesting_facts2.cpp

/**
 * 抽象类类型的指针和引用
*/

#include <iostream>
using namespace std;

/**
 * 抽象类至少包含一个纯虚函数
*/
class Base {
    int x;

    public:
        virtual void show() = 0;
        int getX() { return x; }
};

class Derived : public Base {
    public:
    void show() { cout << "In derived \n"; }
    Derived() {}
};

int main(void) {
    // Base b; // error! 不能创建抽象类的对象
    // Base *b = new Base(); error!
    Base *bp = new Derived(); //抽象类的指针与引用 -> 由抽象类派生出来的类的对象
    bp->show();
    return 0;
}

五,如果我们不在派生类中覆盖纯虚函数,那么派生类也会变成抽象类

interesting_facts3.cpp

/**
 * 如果我们不在派生类中覆盖纯虚函数,那么派生类也会变成抽象类
*/

#include <iostream>
using namespace std;

class Base {
    int x;

    public:
        virtual void show() = 0;
        int getX() { return x; }
};

/**
 * Derived 自动变为抽象类
 */
class Derived : public Base {
    public:
    // void show() {}
};
int main(void) {
    Derived
    d; // error! 派生类没有实现纯虚函数,那么派生类也会变成抽象类,不能创建抽象类的对象
    return 0;
}

六,抽象类可以有构造函数

interesting_facts4.cpp

/**
 * 抽象类可以有构造函数
*/

#include <iostream>
using namespace std;

// An abstract class with constructor
class Base {
    protected:
    int x;
    
    public:
        virtual void fun() = 0;
        // 抽象类的构造函数
        Base(int i) { x = i; }
};

class Derived : public Base {
    int y;

    public:
    // 调用父类构造函数
    Derived(int i, int j) : Base(i) { y = j; }
    // 实现父类抽象函数
    void fun() { cout << "x = " << x << ", y = " << y; }
};

int main(void) {
    Derived d(4, 5);
    d.fun();
    return 0;
}

七,构造函数不能是虚函数,而析构函数可以是虚析构函数。

interesting_facts5.cpp

/**
 * 构造函数不能是虚函数,而析构函数可以是虚析构函数。
 * 例如:当基类指针指向派生类对象并删除对象时,我们可能希望
 * 调用适当的析构函数。如果析构函数不是虚拟的,则只能调用基类的析构构函数。
*/

#include <iostream>
using namespace std;

class Base {
    public:
    Base() { cout << "Constructor: Base" << endl; }
    virtual ~Base() { cout << "Destructor: Base" << endl; }
};

class Derived : public Base {
    public:
        Derived() { cout << "Constructor: Derived" << endl; }
        ~Derived() { cout << "Destructor: Derived" << endl; }
};

int main() {
    Base *Var = new Derived();
    delete Var;
    return 0;
}

八, 纯虚函数:没有函数体的虚函数。抽象类:包含纯虚函数的类

pure_virtual.cpp

/**
 * 纯虚函数:没有函数体的虚函数
 * 抽象类:包含纯虚函数的类
*/

#include <iostream>

using namespace std;

class A {
    private:
        int a;

    public:
        virtual void show() = 0; // 纯虚函数
};

int main() {

    /**
     * 1. 抽象类只能作为基类来派生新类使用
     * 2. 抽象类的指针和引用->由抽象类派生出来的类的对象!
    */

   A a; // error 抽象类,不能创建对象
   A *a1; // ok 可以定义抽象类的指针
   A *a2 = new A(); // error,A是抽象类,不能创建对象
}

<think>首先,用户的问题是:“我想了解C++抽象类的定义和用法请问C++抽象类定义用法”,这是在询问关于C++抽象类的定义和用法。用户已经提供了三个参考引用,但这些引用是关于C++抽象类的示例代码,我需要基于这些以及之前的交互来回答。回顾系统级指令:-所有行内数学表达式必须使用$...$格式。-独立公式必须使用$$...$$格式并单独成段。-LaTeX语法正确。-使用中文回答。-生成相关问题。-回答中引用的段落末尾自然地添加引用标识。-回答结构清晰,帮助用户逐步解决问题。-尽量保证回答真实可靠。用户的问题是关于C++抽象类的,这是一个编程话题,可能涉及类、虚函数等,而不是数学表达式。因此,我应该避免在回答中使用LaTeX数学表达式,除非必要。问题中没有涉及数学,所以我直接专注于C++概念。参考引用:-引用[1]:定义了抽象类Animal,有纯虚函数MakeSound()和非虚方法Eat()。-引用[2]:定义了抽象类IShape,有纯虚函数getArea()和getName()。-引用[3]:定义了抽象类Shape,有纯虚函数getArea()和getPerimeter()。这些引用都是正确的C++抽象类示例,我需要整合它们来定义和解释用法。结构化回答:-回答应该清晰,逐步解释定义和用法。-定义:解释什么是抽象类。-用法:如何定义、继承、使用纯虚函数等。-自然地添加引用标识。例如,当引用某个部分时,加[^1],[^2]等。-在末尾生成相关问题。之前系统指令中的示例是关于快速排序的,但我这里没有之前的交互,所以从这个开始。用户说“请尽可能多的参考用户上一次的问题和你的回答”,但在这个对话中,没有之前的问题,所以这是第一次。用户说“上述引用仅供参考”,所以我应该基于用户的问题:“C++抽象类定义用法”。关键点:-**抽象类定义**:C++中,抽象类是不能被实例化的类,通常包含至少一个纯虚函数(purevirtualfunction)。纯虚函数用=0;指定。-**纯虚函数**:在类声明中使用=0;声明,没有实现,必须由派生类覆盖。-**用途**:定义接口,强制派生类实现特定方法,确保多态行为。整合引用:-从引用[1]:抽象类定义示例。-从引用[2]和[3]:类似示例。回答结构:1.**引言**:简要解释抽象类的重要性。2.**定义**:逐步展示如何定义抽象类。3.**用法**:如何继承抽象类,实现纯虚函数,使用指针或引用来实现多态。4.**示例**:给出简单的代码示例,集成来自引用的内容。5.**总结**:复习关键点。6.**相关问题**:在最后生成相关问题。使用中文回答:-整个回答用中文。生成相关问题:-像系统示例一样,在末尾添加“§§相关问题§§”并列出问题。-例如:"1.如何实现抽象类的继承?2.抽象类有哪些限制?3.抽象类的实际应用案例?"添加引用标识:-当引用具体段落时,加[^1],但在回答中,我需要自然地提及这些引用中的内容。-例如,在展示示例时,说如引用[1]所示。LaTeX注意:-可能没有太多数学表达式,除非解释语法时涉及类型。-对于类定义,我不需要使用LaTeX,因为是代码;但在文本中,描述语法时可以用行内格式。-例如,纯虚函数定义为virtualvoidfunc()=0;可以写成文本或代码块。代码格式化:-系统指令提到在回答中可以有代码块,如Python示例。-所以,我应该包括C++代码示例。完整回答大纲:1.**解释抽象类概念**:C++中,抽象类是一个包含至少一个纯虚函数的类,不能被实例化。2.**如何定义**:使用纯虚函数。从引用中提取代码。3.**用法**:-继承:派生类必须实现所有纯虚函数,否则也抽象。-多态使用:通过基类指针或引用调用函数。4.**好处**:强制接口实现,支持设计模式如策略模式等。5.**注意事项**:不能创建对象;可以有非虚函数;等等。6.**综合示例**:创建一个简单示例。7.**相关问题**。生成问题:-类似于示例中的快速排序问题。-例如:"1.如何确保派生类实现了所有纯虚函数?2.抽象类与接口的区别?3.在C++11中有什么新增特性?"最终输出格式:-使用Markdown式代码块等。</think> ### C++抽象类的定义和用法详解 C++抽象类是一种特殊的类,它不能被直接实例化(即不能创建对象),主要用于定义一个基类接口,强制派生类实现特定的方法。这是通过纯虚函数来实现的,纯虚函数在声明时用 `= 0;` 指定,没有具体实现,必须在派生类中被覆盖。抽象类常用于实现多态和接口统一,提高代码的扩展性和可维护性。下面我将从定义、用法逐步解释,并提供一个完整的示例。 #### 1. C++抽象类的定义 抽象类在C++中定义为包含至少一个纯虚函数的类。纯虚函数的声明格式为 `virtual 返回类型 函数名(参数列表) = 0;`。抽象类本身不能被创建对象实例,但可以定义非虚方法,这允许类既有接口行为又有部分实现逻辑。以下是基于参考引用的关键点: - **纯虚函数**:强制派生类必须实现该方法,否则派生类也会被视为抽象类。 - **非虚方法**:抽象类中可以包含普通成员函数,提供默认行为[^1]。 - **定义规则**: - 使用 `class` 关键字定义类。 - 在类声明内部指定纯虚函数。 - 可以有构造器和析构器,但必须通过派生类实例化[^3]。 例如,参考引用[1]和[3]中的示例: ```cpp // 抽象类示例:定义Shape类,含纯虚函数 class Shape { public: // 纯虚函数:计算面积,派生类必须实现 virtual double getArea() = 0; // 纯虚函数:计算周长,派生类必须实现 virtual double getPerimeter() = 0; // 非虚方法:可选提供默认行为 void display() { std::cout << "这是一个形状类" << std::endl; } }; ``` 在这个定义中,`getArea()` 和 `getPerimeter()` 是纯虚函数,使 `Shape` 成为抽象类[^3][^1]。任何尝试创建 `Shape` 对象的语句(如 `Shape s;`)会编译错误。 #### 2. C++抽象类的用法 抽象类主要用于接口继承和多态实现。用法包括: - **继承抽象类**:派生类必须覆盖所有纯虚函数才能被实例化。如果派生类没有完全覆盖,它也会成为抽象类。 - **使用多态**:通过基类指针或引用来访问派生类对象,实现运行时绑定,这允许灵活的代码设计。 - **优点**: - **接口强制**:确保所有派生类遵循相同的方法签名,避免错误实现。 - **代码复用**:通过非虚方法共享公共逻辑,减少重复代码[^1]。 - **支持设计模式**:常用于工厂模式、策略模式等场景。 ##### 代码用法示例 基于参考引用[2],我们定义一个抽象类 `IShape` 和一个派生类: ```cpp // 抽象类定义 (类似引用[2]) class IShape { public: // 纯虚函数:获得面积 virtual float getArea() = 0; // 纯虚函数:返回名称 virtual std::string getName() = 0; }; // 派生类Circle:实现抽象类 class Circle : public IShape { private: float radius; public: Circle(float r) : radius(r) {} // 覆盖纯虚函数:必须提供具体实现 float getArea() override { return 3.14f * radius * radius; // π*r^2 } std::string getName() override { return "Circle"; } }; // 使用示例 int main() { // 不能创建抽象类对象:IShape s; // 编译错误 Circle circle(5.0f); // 实例化派生类 // 使用基类指针实现多态 IShape* shapePtr = &circle; std::cout << "Name: " << shapePtr->getName() << ", Area: " << shapePtr->getArea() << std::endl; // 输出: Name: Circle, Area: 78.5 return 0; } ``` 在这个用法中: - `Circle` 继承了 `IShape` 并覆盖了所有纯虚函数,因此可以被实例化。 - 通过 `IShape*` 指针调用方法,实现了多态:运行时解析到 `Circle` 的实现[^2]。 - 非虚方法可以从抽象类中移到派生类以提供默认行为[^1]。 #### 3. 注意事项和最佳实践 - **不能实例化**:抽象类不能创建对象,仅作为基类使用。 - **覆盖要求**:在派生类中,使用 `override` 关键字明确表示覆盖纯虚函数,提高可读性和编译检查。 - **构造函数**:抽象类可以有构造器,用于初始化成员变量,派生类会调用基类构造器。 - **现代C++C++11及以上)**:推荐使用 `override` 和 `final` 关键字来增强安全性和性能优化。 - **好处**:抽象类简化了大型项目中模块化设计,但应避免过度使用,以免增加不必要复杂性。例如,在UI框架中定义一个抽象类 `Widget`,强制所有控件实现 `draw()` 方法。 #### 总结 C++抽象类通过纯虚函数定义接口,强制派生类实现特定方法,确保代码的一致性和扩展性。定义时需包含 `virtual ... = 0;` 声明,用法上依赖多态实现动态行为。参考引用的例子展示了其核心语法和场景[^1][^2][^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值