QT学习之C++面向对象基础
1. 类和对象
1.1 类的定义
C++中的类可以简单看作是结构体的升级版,但是在类中成员不仅可以是变量也可以是函数。变量可以称作类的属性,函数可以称为类的方法。
示例:
class stduent
{
public:
int id;//成员之1
int age;//成员之2
void test(void);//成员之3,函数
private:
int score;//成员之4
};
创建的方法类似结构体的定义方法,关键字 public 确定了类的成员的访问属性。在类对象作用域内,公共成员在类的外部是可访问的。也可以指定类的成员为 private 或 protected,表明成员只能在类的内部进行访问。
1.2 创建对象
对象是类的实例化,使用对象可以访问类的成员,创建方法有两种。
可以使用下面方法直接创建:
//类名 对象名
student stdent1;//创建一个student类的对象student1
或者使用new方法在堆中创建:
student *student1 = new student;
使用这种方法创建的对象,可以使用delete
方法删除,删除后就可以释放堆中的内存。如:
delete student1;
1.3 类的成员函数
成员函数也是类的成员,可以在类中直接定义,也可以在类中声明,在外部定义。
在类中定义:
class student
{
public:
int id;//成员之1
int age;//成员之2
void test(void){//成员函数
printf("internal class\n");
}
private:
int score;//成员之3
};
在外部定义时,需要使用范围解析运算符 :: 表明函数所属的类,格式如下:
返回值 类名::函数名(参数)
class student
{
public:
int id;//成员之1
int age;//成员之2
void test(void);//声明成员函数
private:
int score;//成员之3
};
void student::test(void)//成员函数定义
{
printf("external class\n");
}
1.4 访问类的成员
使用对象可以在外部访问类的public成员,使用普通方法创建的对象使用(.)访问,使用指针new创建的对象则使用(->)访问,与C语言中的结构体成员访问方法类似。
注意:默认无修饰符的类成员是private或者protected的。
#include <iostream>
using namespace std;
class student
{
public:
int id;//成员之1
int age;//成员之2
void test(void);
private:
int score;//成员之3
};
//成员函数
void student::test(void)
{
printf("class function!\n");
}
int main()
{
student student1;
student *student2 = new student;
//访问类的成员变量
student1.id = 20;
student2->id = 21;
//访问类的成员函数
student1.test();
student2->test();
cout << "student1.id = " << student1.id << endl;
cout << "student2->id = " << student2->id << endl;
cout << "Hello World!" << endl;
return 0;
}
2. 特殊的函数
2.1 重载函数
在一个类中,可以定义同名但函数参数不相同的成员函数,当外部调用时,会自动根据调用函数时传递的参数,来选择对应的函数进行调用。这些函数就是重载函数,C++的这种特性称做重载特性。
在student类中定义三个同名的test
函数,每个函数的参数均不相同,调用时传递不同参数调用不同函数。
#include <iostream>
using namespace std;
class student
{
public:
int id;//成员之1
int age;//成员之2
void test(char Chinese[]);
void test(int Math);
void test(float Physic);
private:
int score;//成员之3
};
void student::test(char Chinese[])
{
cout << "Get Chinese Score!" << endl;
}
void student::test(int Math)
{
cout << "Get Math Score!" << endl;
}
void student::test(float Physic)
{
cout << "Get Physic Score!" << endl;
}
int main()
{
student student1;
char c[] = "Chinese";
student1.test(c);
student1.test(100);
float n=100.0;
student1.test(n);
cout << "Hello World!" << endl;
return 0;
}
运行结果:
2.2 构造函数
构造函数是类的一个特殊成员函数,当使用类创建一个对象时,就会执行这个类的构造函数。
构造函数的名字与类的名字完全一致,构造函数可以带参数,但无返回值。
无参数的构造函数:
class student
{
public:
int id;//成员之1
int age;//成员之2
void SetScore(int Setscore);//成员函数
int GetScore(void);//成员函数
student();//构造函数
private:
int score;//成员之3
};
//构造函数,名字需要与类相同
student::student(){
cout << "student Object is created!" << endl;
}
主函数:
int main()
{
student student1;//创建对象时会调用构造函数
cout << "Hello World!" << endl;
return 0;
}
结果:
带参数的构造函数:
默认的构造函数没有参数, 需要时可以给构造函数设置参数,传递给类的成员进行初始化操作。需要才创建对象时,传递参数,格式如下:
类名 对象名(参数列表);
如下通过构造函数对类的私有成员score
进行赋值操作:
#include <iostream>
using namespace std;
class student
{
public:
int id;//成员之1
int age;//成员之2
void SetScore(int Setscore);//成员函数
int GetScore(void);//成员函数
student(int Score);//构造函数
private:
int score;//成员之3
};
//构造函数
student::student(int Score){
cout << "student Object is created!" << endl;
score = Score;
}
//函数功能:设置成绩score
void student::SetScore(int Setscore)
{
score = Setscore;
}
//函数功能:获取成绩score
int student::GetScore(void)
{
return score;
}
int main()
{
student student1(100);//创建对象时,使用构造函数传递参数score的值为100
cout << "Init score = " << student1.GetScore() << endl;//打印score
student1.SetScore(99);//重新设置score的值
cout << "Set score = " << student1.GetScore() << endl;//打印score
cout << "Hello World!" << endl;
return 0;
}
输出结果:
2.3 析构函数
析构函数与构造函数相反,当类的对象被删除时执行,同样没有返回值,但是与构造函数不同,析构函数不可以带参数。
析构函数的名字也与类的名字相同,但是需要在函数名前加~符号。
析构函数可以在跳出程序(比如关闭文件、释放内存等)前进行释放资源等操作。
主函数中使用类创建对象时会调用构造函数,程序运行结束对象被删除时会调用析构函数:
#include <iostream>
using namespace std;
class student
{
public:
int id;//成员之1
int age;//成员之2
student(int Score);//构造函数
~student(void);//析构函数
private:
int score;//成员之3
};
//构造函数
student::student(int Score){
cout << "student Object is created!" << endl;
score = Score;
}
student::~student(void)
{
cout << "student Object is deleted!" << endl;
}
int main()
{
student student1(100);
cout << "Hello World!" << endl;
return 0;
}
运行结果:
3. 类的继承
面向对象中继承是一个非常重要的部分。类的继承就是在一个旧的类基础上定义一个新的类,这个新类称为子类,旧类称为父类。子类可以拥有父类部分或全部的属性和方法,这就是继承。新生成的子类可以在父类的基础上修改父类的成员,可以添加更多的属性、方法,可以大大开发提高效率。
继承格式:
class 子类: 继承类型(public/private/protected) 父类
继承类型:类的成员有public、private、protected三种类型,继承时可以选择将父类的public和protected成员(private成员不可继承)继承为子类的public、private、protected成员。所以有三种继承类型:
- 公有继承(public):当一个子类派生自父类的public时,子类的public和protected成员与父类相同。
- 保护继承(protected): 当一个子类派生自父类的protected时,子类的public和protected成员将成为子类的protected成员。
- 私有继承(private):当一个子类派生自父类的private时,子类的public和protected成员将成为子类的private成员。
定义一个Animal动物类,再定义一个Dog类(公有继承自Animal类),Dog的对象可以获得Animal的public和protected成员。
子类Dog可以修改父类Animal的已有成员name、Eat(),同时继承了父类的Drink()成员,添加了Bark()。
#include <iostream>
using namespace std;
//animal类
class Animal
{
public:
char *name="--->I am an animal<---";
void Eat(void);//成员函数(技能1):吃
void Drink(void);//成员函数(技能2):喝
private:
void AniamlPrint(void);
};
//吃
void Animal::Eat(void)
{
cout << "I can eat.." << endl;
}
//喝
void Animal::Drink(void)
{
cout << "I can drink.." << endl;
}
//Dog类继承自Animal类public部分,公有继承
class Dog: public Animal
{
public:
char *name="--->I am a dog<---";
void Eat(void){
cout << "I can eat!" << endl;
}
void Bark(void);//吠,Dog的成员
};
//吠
void Dog::Bark(void)
{
cout << "I can bark.." << endl;
}
int main()
{
Animal animalA;
Dog WangWang;
cout << animalA.name << endl;
animalA.Eat();
animalA.Drink();
cout << WangWang.name << endl;
WangWang.Eat();
WangWang.Drink();
WangWang.Bark();
return 0;
}
运行结果:
虚函数
虚函数也是类的成员函数,需要在函数名前加上virtual关键字声明为虚函数。
定义虚函数的目的:为了允许用父类的指针来调用子类的这个函数。
可以用下面这个例子进行说明:
//来自菜鸟教程
#include <iostream>
using namespace std;
class A{
public:
virtual void foo()
{
std::cout << "A::foo() is called" << endl;
}
};
class B: public A
{
public:
void foo()
{
std::cout << "B::foo() is called" << endl;
}
};
int main(int argc, char *argv[]) {
A *a = new B();
a->foo();
return 0;
}
*A a = new B();这条语句的意思是创建一个A类型的指针,指向B类的对象。根据指针的指向关系,使用a访问foo()函数自然会调用B类的foo(),因为a指向的是B的对象。这样就实现了使用父类(类型为A)的指针访问子类(B)的函数。
结果:
纯虚函数
纯虚函数同样使用virtual关键字进行修饰,但纯虚函数只在父类中进行声明,没有函数的定义(功能实现)。当其他的子类继承这个父类时,都必须实现这个纯虚函数。
定义纯虚函数的目的:实现一个接口,起到一个规范的作用,规范继承这个类的程序员必须实现这个函数。
#include <iostream>
using namespace std;
class A{
public:
virtual void foo()=0;//纯虚函数,只有声明,无定义
};
class B: public A//B继承自A
{
public:
void foo()//子类B中进行纯虚函数的定义
{
std::cout << "foo() is Pure virtual function!" << endl;
}
};
int main() {
B b;
b.foo();
return 0;
}
结果: