个人网站上传有啥要求,wordpress播放网盘视频播放,如何进行电子商务网站建设,什么平台可以找客源这里主要介绍概念为主#xff0c;主要介绍 C与 C 语言中常用的不同点#xff0c;和一些新的变化。其中不会去说指针、数据类型、变量类型、判断和循环等这些知识#xff0c;这些和C 语言基本是一样使用的。我们主要学习 C的面向对象编程#xff0c;对学习 Qt 有很大的帮助。…         这里主要介绍概念为主主要介绍 C与 C 语言中常用的不同点和一些新的变化。其中不会去说指针、数据类型、变量类型、判断和循环等这些知识这些和C 语言基本是一样使用的。我们主要学习 C的面向对象编程对学习 Qt 有很大的帮助。 1、C语言新特性 
1.1 C语言新特性 C比 C 语言新增的数据类型是布尔类型bool。但是在新的 C 语言标准里已经有布尔类型了但是在旧的 C 语言标准里是没有布尔类型的编译器也无法解释布尔类型。在传统的 C 语言里变量初始化时必须在程序的前面定义在前面而 C则是可以随用随定义。C也可以直接初始化比如 int x(100);这样就直接赋值 x100这些都是 C特性的好处。这里只说这些常用的新特性其他特性不做描述或者解释了。 1.2 C的输入输出方式 在 C 语言里我们是这样输入或者输出的。 在 C里我们使用以 cin 和 cout 代替了 scanf 和 printf。在输入和输出的流程上是不变的只是关键字变了用法也变了。 要说效率上肯定是 C 语言的 scanf 和 printf 的效率高但是没有 C中的 cin 和 cout 使用方便。          C的 I/O 语法方式如下。          cout 语法形式 coutxendl;         x 可以是任意数据类型甚至可以写成一个表达式这比 C 语言需要指定数据类型方便多了endl 指的是换行符与 C 语言的“\n”效果一样。 错误示例   coutx,yendl;  // 在变量间不能用“”。  正确写法   coutxy;    // endl 可流省略只是一个换行的效果。  cin 语法形式   cinx;          x 可以是任意数据类型。  拓展如何输入两个不同的变量。 cinxy; 1.3  C之命名空间 namespace 如下代码第 2 行。using namespace std;同时我们要注意第 1 行不能写成 iostream.h有.h 的是非标准的输入输出流c 的标准库。无.h 的是标准输入输出流就要用命名空间。 #include iostream
using namespace std;
int main()
{cout  Hello, World!  endl;return 0;
}         using 是编译指令声明当前命名空间的关键词。可以从字面上理解它的意思using 翻译成使用。这样可以理解成使用命名空间 std。因为 cin 和 cout 都是属于 std 命名空间下的东西所以使用时必须加上 using namespace std;这句话。cin 和 cout 可以写 std::cin 和 std::cout“::” 表示作用域cin 和 cout 是属于 std 命名空间下的东西这里可以理解成 std 的 cin 和 std 的 cout。          为什么要使用命名空间          有些名字容易冲突所以会使用命名空间的方式进行区分具体来说就是加个前缀。比如C 标准库里面定义了 vector 容器您自己也写了个 vector 类这样名字就冲突了。于是标准库里的名字都加上 std:: 的前缀您必须用 std::vector 来引用。同理您自己的类也可以加个自定义的前缀。但是经常写全名会很繁琐所以在没有冲突的情况下您可以偷懒写一句using namespace std;接下去的代码就可以不用写前缀直接写 vector 了。          从命名空间开始我们就隐隐约约可以看到 C面向对象的影子了。命名空间在很多 C库里使用到。有些公司也会自定义自己的 C库里面使用了大量的命名空间。从这里我们也可以看出 C是非常之有条理的容易管理的不含糊易使用的。          在初学 Qt 时我们是比较少使用命名空间或者比较少看到命名空间。当然也是可以在 Qt里自定义命名空间然后与 C一样正常使用。 下面通过一个简单的例子来介绍自定义的命名空间和使用自定义的命名空间。在 Ubuntu上我们新建一个目录 02_namespace_example然后在 02_namespace_example 里新建一个  02_namespace_example.cpp 文件内容如下。 #include iostream
using namespace std;namespace A
{int x  1;void fun() {coutA namespaceendl;}
}
using namespace A;
int main()
{fun();A::x  3;coutA::xendl;A::fun();return 0;
}         第 4 行自定义了命名空间 A里面定义了一个变量 x并将 x 赋值为 1定义了一个函数fun()并在 fun()加了输出打印语句 coutA namespaceendl;。          第 11 行声明使用命名空间 A。          第 14 行在第 11 行声明了命名空间 A 后才能直接使用 fun();否则要写成 A::fun();          第 15 行将 A 命名空间下的 x 重新赋值为 3。          第 16 行打印出 A 命名空间下的 x 的值。          第 17 行调用 A 命名空间下的 fun()。          执行下面的指令开始编译。 g 02_namespace_example.cpp -o 02_namespace_example 2、C面向对象 2.1 类和对象 C 在 C 语言的基础上增加了面向对象编程C 支持面向对象程序设计。类是 C的核心特性通常被称为用户定义的类型。类用于指定对象的形式它包含了数据表示法和用于处理数据的方法。类中的数据和方法称为类的成员。函数在一个类中被称为类的成员。          打个比方说明一下什么是类比如有一条小狗小狗有名字叫旺财旺财的年龄是 2 岁同时旺财会汪汪的叫也能跑。我们统称狗这个为类类是我们抽象出来的因为狗不只有上面的属性还有体重毛发的颜色等等我们只抽象出几种属性成一个类。具体到哪条狗就叫对象。          从类中实例化对象分两种方法一种是从栈中实例化对象一种是从堆中实例化对象。          下面以自定义狗类介绍如何自定义类和如何使用对象。          在 Ubuntu 上编辑一个 03_class_dog_example 目录在 03_class_dog_example 目录下新建一个 03_class_dog_example.cpp 文件内容如下。 #include iostream
#include string
using namespace std;class Dog
{public:string name;int age;void run() {cout小狗的名字是:name,年龄是ageendl;}
};int main()
{Dog dog1;dog1.name  旺财;dog1.age  2;dog1.run();Dog *dog2  new Dog();if (NULL  dog2) {return 0;}dog2-name  富贵;dog2-age  1;dog2-run();delete dog2;dog2  NULL;return 0;
}         第 5 行定义了一个 Dog 狗定义类时起的类名要尽量贴近这个类让人一看就明白您这个类是做什么的。          第 7 行访问限定符 public公有的此外还有 private私有的和 protected受保护的。写这个的目的是为了下面我们要调用这些成员不写访问限定符默认是 private。关于访问限定符如果是初学者可能会难理解。简单的来说访问限定符就是设置一个成员变量和成员函数的访问权限而已初学者暂时不必要深究什么时候应该用 public 和什么时候应该用 private。          第 8 至 11 行定义了一个字符串变量 name整形变量 age。和一个方法 run()。我们在这个 run()里打印相应的狗名和狗的年龄。PSstring 是 C的数据类型方便好用使用频率相当高。          第 18 行从栈中实例化一个对象 dog1(可以随意起名字)。          第 20 至 22 行为 dog1 的成员变量赋值dog1 的 name 赋值叫“旺财”年龄为 2 岁。然后调用 run()方法打印 dog1 的相关变量的信息。          第 24 行从堆中实例化对象使用关键字 new 的都是从堆中实例化对象。          第 26 行从堆中实例化对象需要开辟内存指针会指向那个内存如果 new 没有申请内存成功p 即指向 NULL程序就自动退出下面的就不执行了写这个是为了严谨。          第 29 至 31 行和 dog1 一样为 dog2 的成员赋值。          第 34 和 35 行释放内存将 dog2 重新指向 NULL。          如果没有语法错误我们完全可以预测到打印的结果。我们学习 C 语言的结构体类其实和结构类似可以说类是结构体的升级版本。          执行下面的指令开始编译。 g 03_class_dog_example.cpp -o 03_class_dog_example         通过上面的例子我们已经学习了什么是类和什么是对象。以描述 Dog 为一类抽象出来的从 Dog 类中实例出来就是对象实际事物。对象拥有 Dog 类里的属性可以从栈中实例化对象亦可从堆中实例化对象。类的编写过程和对象的使用过程大致如上了。我们只需要理解这个步骤明白类的定义和使用即可。 2.1.1 构造函数与析构函数 什么是构造函数构造函数在对象实例化时被系统自动调用仅且调用一次。构造函数出现在哪里前面我们学过类实际上定义类时如果没有定义构造函数和析构函数编译器就会生成一个构造函数和析构函数只是这个构造和析构函数什么事情也不做所以我们不会注意到一点。          构造函数的特点如下          1 构造函数必须与类名同名          2 可以重载重载新概念后面学到什么是重载。          3 没有返回类型即使是 void 也不行。          什么是析构函数与构造函数相反在对象结束其生命周期时系统自动执行析构函数。实际上定义类时编译器会生成一个析构函数。          析构函数的特点如下          1 析构函数的格式为~类名()          2 调用时释放内存资源          3 ~类名()不能加参数          4 没有返回值即使是 void 也不行。          下面我们通过简单的例子来说明构造函数和析构函数的使用。新建一个目录04_structor_example编辑一个 04_structor_example.cpp 内容如下。 #include iostream
#include string
using namespace std;class Dog
{
public:Dog();~Dog();
};
int main()
{Dog dog;cout构造与析构函数示例endl;return 0;
}Dog::Dog()
{cout构造函数执行endl;
}Dog::~Dog()
{cout析构函数执行endl;
} 2.1.2 this 指针 一个类中的不同对象在调用自己的成员函数时其实它们调用的是同一段函数代码那么成员函数如何知道要访问哪个对象的数据成员呢没错就是通过 this 指针。每个对象都拥有一个 this 指针this 指针记录对象的内存地址。在 C中this 指针是指向类自身数据的指针简单的来说就是指向当前类的当前实例对象。关于类的 this 指针有以下特点          1 this 只能在成员函数中使用全局函数、静态函数都不能使用 this。实际上成员函数默认第一个参数为 T * const this。也就是一个类里面的成员了函数 int func(int p)func 的原型在编译器看来应该是 int func(T * const this,int p)。          2 this 在成员函数的开始前构造在成员函数的结束后清除。          3 this 指针会因编译器不同而有不同的放置位置。可能是栈也可能是寄存器甚至全局变量。 下面以简单的例子来说明 this 的用法。我们还是以狗类为例按上面的 this 解释this 只能够在成员函数使用并可以指向自身数据。我们就可以写这样简单的例子来说明 this 的用法。          我们在 Qt 里也会遇到 this 这个东西下面这个例子就很容易解释 Qt 里的 this 指针的用法。          新建一个目录 05_this_pointer_example编辑一个 05_this_pointer_example.cpp 内容如下。 #include iostream
#include string
using namespace std;class Dog
{public:string name;void func();
};int main()
{Dog dog;dog.func();return 0;
}void Dog::func()
{this-name  旺财;cout小狗的名字叫this-nameendl;
}         第 21 和 22 行在类的成员函数里使用了 this 指针并指向了类里的成员 name。先将 name赋值叫“旺财”然后我们打印 name 的值。          当程序没有语法错误里我们可以预测打印的结果就是“小狗的名字叫旺财”。 2.2 继承 面向对象程序设计中最重要的一个概念是继承。继承允许我们依据另一个类来定义一个类这使得创建和维护一个应用程序变得更容易。这样做也达到了重用代码功能和提高执行效率的效果。 当创建一个类时您不需要重新编写新的数据成员和成员函数只需指定新建的类继承了一个已有的类的成员即可。这个已有的类称为基类新建的类称为派生类。在 Qt 里大量的使用了这种特性当 Qt 里的类不满足自己的要求时我们可以重写这个类就是通过继承需要重写的类来实现自己的类的功能。          一个类可以派生自多个类这意味着它可以从多个基类继承数据和函数。定义一个派生类我们使用一个类派生列表来指定基类。类派生列表以一个或多个基类命名形式如下 class derived-class: access-specifier base-class         与类的访问修饰限定符一样继承的方式也有几种。其中访问修饰符 access-specifier 是 public、protected 或 private 其中的一个base-class 是之前定义过的某个类的名称。如果未使用访问修饰符 access-specifier则默认为 private。          下面来捋一捋继承的方式例子都是以公有成员和公有继承来说明其他访问修饰符和其他继承方式大家可以在教程外自己捋一捋。这个公有成员和继承方式也没有什么特别的无非就是不同的访问权限而已可以这样简单的理解。          1. 公有继承public当一个类派生继承公有基类时基类的公有成员也是派生类的公有成员基类的保护成员也是派生类的保护成员基类的私有成员不能直接被派生类访问但是可以通过调用基类的公有和保护成员来访问。          2. 保护继承protected 当一个类派生继承保护基类时基类的公有和保护成员将成为派生类的保护成员。          3. 私有继承private当一个类派生继承私有基类时基类的公有和保护成员将成为派生类的私有成员。          下面我们还是以狗类为例在 2.2.1 小节里我们定义的狗类已经定义了 nameage 和 run() 方法。假设我们不想重写这个狗类而是新建一个 Animal 类让狗类去继承这个 Animal 类。假设是公有继承那么我们是不是可以在狗类实例的对象里去使用继承 Animal 类里的成员呢带着这个疑问我们使用下面的例子来说明。          新建一个目录 06_inherit_example编辑一个 06_inherit_example.cpp 内容如下。 #include iostream
#include string
using namespace std;/*动物类抽象出下面两种属性
*颜色和体重是每种动物都具有的属性
*/
class Animal
{
public:/* 颜色成员变量 */string color;/* 体重成员变量 */int weight;
};/*让狗类继承这个动物类并在狗类里写自己的属性。
*狗类拥有自己的属性 nameagerun()方法同时也继承了
*动物类的 color 和 weight 的属性
*/
class Dog : public Animal
{
public:string name;int age;void run();
};int main()
{Dog dog;dog.name  旺财;dog.age  2;dog.color  黑色;dog.weight  120;cout狗的名字叫dog.nameendl;cout狗的年龄是dog.ageendl;cout狗的毛发颜色是dog.colorendl;cout狗的体重是dog.weightendl;return 0;
}         第 21 行Animal 作为基类Dog 作为派生类。Dog 继承了 Animal 类。访问修饰符为 public  公有继承。 2.3 重载 C 允许在同一作用域中的某个函数和运算符指定多个定义分别称为函数重载和运算符重载。 重载声明是指一个与之前已经在该作用域内声明过的函数或方法具有相同名称的声明但 是它们的参数列表和定义实现不相同。          当您调用一个重载函数或重载运算符时编译器通过把您所使用的参数类型与定义中的参 数类型进行比较决定选用最合适的定义。选择最合适的重载函数或重载运算符的过程称为重载决策。 2.3.1 函数重载 在同一个作用域内可以声明几个功能类似的同名函数但是这些同名函数的形式参数指 参数的个数、类型或者顺序必须不同。我们不能仅通过返回类型的不同来重载函数。在 Qt 源码里运用了大量的函数重载所以我们是有必要学习一下什么是函数重载。不仅在 C 在其他语言的里都能看见函数重载。因为需要不同所以有重载各种各样的函数。          下面通过一个小实例来简单说明一下函数重载的用法。我们还是以狗类为说明现在假设 有个需求。我们需要打印狗的体重分别以整数记录旺财的体重和小数记录旺财的体重同时 以整数打印和小数打印旺财的体重。那么我们可以通过函数重载的方法实现这个简单的功能。          新建一个目录 07_func_overloading编辑一个 07_func_overloading.cpp 内容如下。 #include iostream
#include string
using namespace std;
class Dog
{
public:string name;void getWeight(int weight) {coutname的体重是weightkGendl;}void getWeight(double weight) {coutname的体重是weightkGendl;}
};
int main()
{Dog dog;dog.name  旺财;dog.getWeight(10);dog.getWeight(10.5);return 0;
}         第 9 行写了一个方法 getWeight(int weight)以 int 类型作为参数。          第 13 行以相同的函数名 getWeight不同的参数类型 double weight这样就构成了函数  重载。          第 22 行与第 23 行分别传进参数不同的参数程序就会匹配不同的重载函数。 2.3.2 运算符重载 运算符重载的实质就是函数重载或函数多态。运算符重载是一种形式的 C多态。目的在于让人能够用同名的函数来完成不同的基本操作。要重载运算符需要使用被称为运算符函数的特殊函数形式运算符函数形式operatorpargument-listoperator 后面的p为要重载的运算符符号。重载运算符的格式如下 返回类型说明符 operator 运算符符号(参数表)
{函数体
}         下面的实例使用成员函数演示了运算符重载的概念。在这里对象作为参数进行传递对象 的属性使用 this 运算符进行访问。下面还是以我们熟悉的狗类为例。声明加法运算符用于把两个 Dog 对象相加的体重相加返回最终的 Dog 对象然后得到第三个 Dog 对象的体重。          新建一个目录 08_operator_example编辑一个 08_operator_example.cpp 内容如下。  #include iostream
#include string
using namespace std;
class Dog
{
public:int weight;Dog operator(const Dog d) {Dog dog;dog.weight  this-weight  d.weight;return dog;}};
int main()
{Dog dog1;Dog dog2;Dog dog3;dog1.weight  10;dog2.weight  20;dog3  dog1  dog2;cout第三只狗的体重是dog3.weightendl;return 0;
}         第 9 至 13 行重载“”运算符注意函数必须与类名同名把 Dog 对象作为传递使用this 运算符进行访问。然后返回一个 dog 对象。  2.4 多态         C多态意味着调用成员函数时会根据调用函数的对象的类型来执行不同的函数形成多态必须具备三个条件          1. 必须存在继承关系          2. 继承关系必须有同名虚函数其中虚函数是在基类中使用关键字 virtual 声明的函数在派 生类中重新定义基类中定义的虚函数时会告诉编译器不要静态链接到该函数          3. 存在基类类型的指针或者引用通过该指针或引用调用虚函数。这里我们还需要理解两个概念          虚函数          是在基类中使用关键字 virtual 声明的函数。在派生类中重新定义基类中定义的虚函数时会告诉编译器不要静态链接到该函数。我们想要的是在程序中任意点可以根据所调用的对象类型来选择调用的函数这种操作被称为动态链接或后期绑定。虚函数声明如下virtualReturnType FunctionName(Parameter) 虚函数必须实现如果不实现编译器将报错          纯虚函数          若在基类中定义虚函数以便在派生类中重新定义该函数更好地适用于对象但是您在基类中又不能对虚函数给出有意义的实现这个时候就会用到纯虚函数。纯虚函数声明如下virtual void funtion1()0; 纯虚函数一定没有定义纯虚函数用来规范派生类的行为即接口。包含纯虚函数的类是抽象类抽象类不能定义实例但可以声明指向实现该抽象类的具体类的指针或引用。          上面那些概念大家可以捋一捋毕竟 C概念还是挺多的。为什么说到多态要与虚函数和纯虚函数扯上关系光说概念没有实例确实难理解。下面我们还是以我们熟悉的狗类和动物类另外加一个猫类进行多态的讲解。           新建一个目录 09_polymorphism_example编辑一个 09_polymorphism_example.cpp 内容如下。PS: polymorphism 翻译多态的意思笔者就以这种方式命名例程了。   #include iostream
#include string
using namespace std;
/* 定义一个动物类 */
class Animal
{
public:virtual void run() {coutAnimal 的 run()方法endl;}
};
/* 定义一个狗类并继承动物类 */
class Dog : public Animal
{
public:void run() {coutDog 的 run()方法endl;}};
/* 定义一个猫类并继承动物类 */
class Cat : public Animal
{
public:void run() {coutCat 的 run()方法endl;}};
int main()
{/* 声明一个 Animal 的指针对象注并没有实例化 */Animal *animal;/* 实例化 dog 对象 */Dog dog;/* 实例化 cat 对象 */Cat cat;/* 存储 dog 对象的地址 */animal  dog;/* 调用 run()方法 */animal-run();/* 存储 cat 对象的地址 */animal  cat;/* 调用 run()方法 */animal-run();return 0;
}         第 9 行、第 18 行和第 28 行都有一个 run()方法。其中我们可以看到基类 Animal 类的 run()方法前面加了关键字 virtual。这样让基类 Animal 类的 run()方法变成了虚函数。在这个例子里我们可以知道虚函数是 C中用于实现多态(polymorphism)的机制。核心理念就是通过基类访问派生类定义的函数。简单的来说上面的实例是基类 Animal 声明了一个指针 animal。然后通过基类的指针来访问 Dog 类对象与 Cat 类的对象的 run()方法前提是基类的 run()方法必须声明为虚函数如果不声明为虚函数基类的指针将访问到基类自己的 run()方法。我们可以尝试把 virtual 关键字去掉再重新编译测试如果不加关键字 virtual 会是什么情况。          第 44 行和第 49 行可以理解是 animal 指针实例化的过程。当基类的 run()方法定义成虚函数编译器不静态链接到该函数它将链接到派生类的 run()方法进行实例化。  2.5 数据封装          封装是面向对象编程中的把数据和操作数据的函数绑定在一起的一个概念这样能避免受到外界的干扰和误用从而确保了安全。数据封装引申出了另一个重要的 OOP 概念即数据隐藏。          数据封装是一种把数据和操作数据的函数捆绑在一起的机制数据抽象是一种仅向用户暴露接口而把具体的实现细节隐藏起来的机制C 通过创建类来支持封装和数据隐藏public、protected、private。          其实我们在第 2.2 小节开始就已经接触了数据封装。在 C程序中任何带有公有和私有成员的类都可以作为数据封装和数据抽象的实例。通常情况下我们都会设置类成员状态为私有private除非我们真的需要将其暴露这样才能保证良好的封装性。这通常应用于数据成员但它同样适用于所有成员包括虚函数。            下面我们还是以狗类为例增加一个食物的方法 addFood(int number)。将获得食物的方法设定在 public 下这样 addFood(int number)方法就暴露出来了也就是对外的接口。然后我们设置狗类的私有成员(private)食物的份数 total。我们在这个教程里第一次使用 private在这章节里我们也可以学到什么时候该使用 private 什么时候使用 public。total 为获得的食物总数然后我们还写一个公开的方法 getFood()在 public 下通过 getFood()来打印出小狗总共获得了几份食物。          新建一个目录 10_encapsulation_example编辑一个 10_encapsulation_example.cpp 内容如下。    #include iostream
#include string
using namespace std;
class Dog
{
public:string name;Dog(int i  0){total  i;}void addFood(int number) {total  total  number;}int getFood() {return total;}
private:int total;
};int main()
{Dog dog;dog.name  旺财;dog.addFood(3);dog.addFood(2);coutdog.name总共获得了dog.getFood()份食物endl;return 0;
}         第 10 至第 13 行在构造函数里初始化 total 的数量不初始化 total 的数量默认是随 int 类型的数。所以我们需要在构造函数里初始化也体现了构造函数的功能一般是在构造函数里初始化。不要在类内直接赋值初始化有可能有些编译器不支持。          第 15 至 17 行addFood(int number)在这个方法里将获得的食物份数赋值给 total。          第 19 至 21getFood()在这个方法里将返回食物的总份数。通过调用这个方法即可访问私有成员的 total 总数。          第 33 和 34 行添加食物的份数。          第 36 行打印食物的总份数。 2.6 数据抽象         数据抽象是指只向外界提供关键信息并隐藏其后台的实现细节即只表现必要的信息而不呈现细节。数据抽象是一种依赖于接口和实现分离的编程设计技术。数据抽象的好处          1. 类的内部受到保护不会因无意的用户级错误导致对象状态受损。          2. 类实现可能随着时间的推移而发生变化以便应对不断变化的需求或者应对那些要求不改变用户级代码的错误报告。          举个简单的例子比如我们生活中的手机。手机可以拍照、听音乐、收音等等。这些都是手机上的功能用户可以直接使用。但是拍照的功能是如何实现的是怎么通过摄像头取像然后怎么在屏幕上显示的过程作为用户是不需要知道的。也就是暴露的不用太彻底用户也不必须知道这种功能是如何实现的只需要知道如何拍照即可。就 C 编程而言C 类为数据抽象提供了可能。它们向外界提供了大量用于操作对象数据的公共方法也就是说外界实际上并不清楚类的内部实现。其实像 cout 这个对象就是一个公共的接口我们不必要知道 cout 是如何在屏幕上显示内容的。cout 已经在底层实现好了。          在上一节我们已经学习过数据封装数据封装是一种把数据和操作数据的函数捆绑在一起的机制而数据抽象是一种仅向用户暴露接口而把具体的实现细节隐藏起来的机制。         C 程序中任何带有公有和私有成员的类都可以作为数据抽象的实例。 2.7 接口抽象类         接口描述了类的行为和功能而不需要完成类的特定实现。C 接口是使用抽象类来实现的抽象类与数据抽象互不混淆数据抽象是一个把实现细节与相关的数据分离开的概念。如果类中至少有一个函数被声明为纯虚函数则这个类就是抽象类。纯虚函数是通过在声明中使用  0 来指定的。          设计抽象类通常称为 ABC的目的是为了给其他类提供一个可以继承的适当的基类。抽象类不能被用于实例化对象它只能作为接口使用。如果试图实例化一个抽象类的对象会导致编译错误。          因此如果一个 ABC 的子类需要被实例化则必须实现每个虚函数这也意味着 C 支持使用 ABC 声明接口。如果没有在派生类中重写纯虚函数就尝试实例化该类的对象会导致编译错误。可用于实例化对象的类被称为具体类。          根据概念我们来写个实例来说明抽象类。          还是以狗类为说明例程与 2.4 小节类似只是 Aninmal 类的 run()方法定义为纯虚函数纯虚函数不用实现由派生类 Dog 和 Cat 类实现重写即可。          新建一个目录 11_abstract_class编辑一个 11_abstract_class.cpp 内容如下。 #include iostream
using namespace std;/* 定义一个动物类 */
class Animal
{
public:virtual void run()  0;
};
/* 定义一个狗类并继承动物类 */
class Dog : public Animal
{
public:void run() {coutDog 的 run()方法endl;}
};/* 定义一个猫类并继承动物类 */
class Cat : public Animal
{
public:void run() {coutCat 的 run()方法endl;}
};int main()
{/* 实例化 dog 对象 */Dog dog;/* 实例化 cat 对象 */Cat cat;/* dog 调用 run()方法 */dog.run();/* cat 调用 run()方法 */cat.run();return 0;
}         虽然结果和例程与 2.4 小节一样但是却表现了两种不同的思想。学 C重要的是思想当我们对这种思想有一种的了解后不管是 Qt 或者其他 C程序我们都能快速学习和了解。C的内容就到此结束了。在这个 C基础中我们的例子非常简单也十分之易懂重要的是理解概念许多 C的课程都是以 C的功能甚至是很复杂的算法作讲解内容复杂且多。只要我们理解好上面的 C的基础对学习 C有很大的帮助。