一、类
class Box
{
public://底下的都声明为public访问限制
double length; // 盒子的长度
double breadth; // 盒子的宽度
Box(void)//析构函数重载
{
length=10;
breadth=10;
}
Box(int length)//使用this指针
{
this->length=length;
breadth=10;
}
Box(int l,int b):length(l),breadth(b)//使用初始化列表来初始化字段
{
length=10;
}
~Box();// 析构函数声明
double getVolume(void)//成员函数方式1:声明为内联函数
{
return length * breadth;
}
void Box::setLength(double len);//成员函数方式2:在类的外部使用范围解析运算符 :: 定义该函数
private://底下的都声明为private访问限制,private和public等访问控制符谁上谁下无所谓
int sell;
};
void Box::setLength(double len)
{
length = len;
}
Box::()
{
}
int main()
{
Box myBox; // 创建一个对象
myBox.getVolume(); // 调用该对象的成员函数
}
类:
- class是首字母小写
成员函数定义:
- 定义成员函数方式1:内联函数形式
- 定义成员函数方式2:在类的外部要使用范围解析运算符 :: 定义该函数
成员函数次序:
不像全局函数一样,顺序还是逆序都可以执行
#include<iostream>
using namespace std;
//顺序
class A
{
public:
void hello()
{
cout<<"A:hello"<<endl;
}
void out()
{
hello();
}
};
//逆序
class B
{
public:
void out()
{
hello();
}
void hello()
{
cout<<"B:hello"<<endl;
}
};
int main()
{
A a;
a.out();
B b;
b.out();
/*
A:hello
B:hello
*/
return 0;
}
静态成员函数:
https://www.baidu.com/s?ie=UTF-8&wd=C++%E9%87%8D%E8%BD%BD%E6%93%8D%E4%BD%9C%E7%AC%A6
构造函数:
- 同成员函数一样:有两种定义形式。
- 可以定义多个析构函数重载,拥有不同参数列表。
- 可以使用初始化列表来初始化字段
析构函数:
- 必须是无参
【理解:析构函数的意义】
答:析构函数一般用来释放指针等,这样方便了项目开发。写完很长的代码后你很容易忘记释放指针,这样对系统是有害的。但当你把含有指针的操作封装成一个类,析构函数中写好释放指针。这样在程序结束时自动释放指针,超方便。
访问控制符:
- 定义类内成员时:默认情况下,类的所有成员都是私有的。
- 继承时:不显示声明是 private,protected,public 继承,则默认是 private 继承,在 struct结构体 中默认 public 继承:
include <iostream>
using namespace std;
class Line {
int a;
};
int main() {
Line line;
line.a = 5;//error
cout << line.a << endl;
//error
/*
这也算是访问控制符
*/
}
#include<iostream>
using namespace std;
class B
{
int a = 10;//默认情况下,类的所有成员都是私有的。
public:
int b = 100;
};
class D:public B{};
int main()
{
D d;
cout<<d.b<<endl;
cout<<d.a<<endl;//error
return 0;
}
#include<iostream>
#include<assert.h>
using namespace std;
class A{
public:
int a;
A(){
a1 = 1;
a2 = 2;
a3 = 3;
a = 4;
}
void fun(){
cout << a << endl; //正确
cout << a1 << endl; //正确
cout << a2 << endl; //正确
cout << a3 << endl; //正确
}
public:
int a1;
protected:
int a2;
private:
int a3;
};
class B : public A{
public:
int a;
B(int i){
A();
a = i;
}
void fun(){
cout << a << endl; //正确,public成员
cout << a1 << endl; //正确,基类的public成员,在派生类中仍是public成员。
cout << a2 << endl; //正确,基类的protected成员,在派生类中仍是protected可以被派生类访问。
cout << a3 << endl; //错误,基类的private成员不能被派生类访问。
}
};
int main(){
B b(10);
cout << b.a << endl;
cout << b.a1 << endl; //正确
cout << b.a2 << endl; //错误,类外不能访问protected成员
cout << b.a3 << endl; //错误,类外不能访问private成员
system("pause");
return 0;
}
#include<iostream>
#include<assert.h>
using namespace std;
class A{
public:
int a;
A(){
a1 = 1;
a2 = 2;
a3 = 3;
a = 4;
}
void fun(){
cout << a << endl; //正确
cout << a1 << endl; //正确
cout << a2 << endl; //正确
cout << a3 << endl; //正确
}
public:
int a1;
protected:
int a2;
private:
int a3;
};
class B : private A{
public:
int a;
B(int i){
A();
a = i;
}
void fun(){
cout << a << endl; //正确,public成员。
cout << a1 << endl; //正确,基类public成员,在派生类中变成了private,可以被派生类访问。
cout << a2 << endl; //正确,基类的protected成员,在派生类中变成了private,可以被派生类访问。
cout << a3 << endl; //错误,基类的private成员不能被派生类访问。
}
};
int main(){
B b(10);
cout << b.a << endl; //正确。public成员
cout << b.a1 << endl; //错误,private成员不能在类外访问。
cout << b.a2 << endl; //错误, private成员不能在类外访问。
cout << b.a3 << endl; //错误,private成员不能在类外访问。
system("pause");
return 0;
}
构造析构顺序:
- main()前顺序构造,main()后逆序析构
- main()下面的也可以运行,被认为是全局变量(但int p=10;写在下面再在mian()中调用就会报错)
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class A
{
private:
int k;
public:
A(int num):k(num)
{
cout << "构造:" << k << endl;
}
~A()
{
cout<<"析构:"<<k<< endl;
}
};
A a(100);
A b(200);
int main()
{
static A x(500);
A y(600);
return 0;
}
A c(300);//main()下面的也是全局变量
/*
构造:100
构造:200
构造:300
构造:500
构造:600
析构:600
析构:500
析构:300
析构:200
析构:100
*/
二、继承
格式:
class SmallBox : public Box
{
}
三、多态
多态是继承的发展,构成多态的条件:
- 必须存在继承关系;
- 继承关系中必须有同名的虚函数,并且它们是覆盖关系(函数原型相同)。
- 存在基类的指针,通过该指针调用虚函数。
例题
针对第二段是否是虚函数
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class B
{
public:
void f()
{
cout << "f():B" << endl;
}
virtual void k()
{
cout << "k():B" << endl;
}
};
class D:public B
{
public:
void f()
{
cout << "f():D" << endl;
}
virtual void k()
{
cout << "k():D" << endl;
}
};
int main()
{
B* p = new D;
p->f();//f():B
p->k();//k():D
/*
f()不是虚函数,所以没有实现多态
k()是虚函数,所以是多态
*/
return 0;
}
针对第二点的虚函数是否都实现
#include <iostream>
using namespace std;
//基类Base
class Base{
public:
virtual void func();
virtual void func(int);
};
void Base::func(){
cout<<"void Base::func()"<<endl;
}
void Base::func(int n){
cout<<"void Base::func(int)"<<endl;
}
//派生类Derived
class Derived: public Base{
public:
void func();
void func(char *);
};
void Derived::func(){
cout<<"void Derived::func()"<<endl;
}
void Derived::func(char *str){
cout<<"void Derived::func(char *)"<<endl;
}
int main(){
Base *p = new Derived();
p -> func(); //输出void Derived::func().调用的是派生类的虚函数,构成了多态。
p -> func(10); //输出void Base::func(int).不是多态
p -> func("http://c.biancheng.net"); //compile error
/*
语句p -> func();派生类和基类都对它进行了实现
语句p -> func(10);调用的是基类的虚函数,因为派生类中没有函数覆盖它。
语句p -> func("http://c.biancheng.net");出现编译错误,因为通过基类的指针只能访问从基类继承过去的成员,不能访问派生类新增的成员。
*/
return 0;
}
针对第三点:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class A
{
public:
virtual f()
{
cout << "A" << endl;
}
};
class B :public A
{
public:
void f(int x)
{
cout << x << endl;
}
};
int main()
{
B myB;
myB.f();//error
/*
这不是多态,不存在指针,更不存在指向基类的指针。所以这只是调用一个类里的成员函数,显而易见,B类没有定义成员函数f()。
*/
return 0;
}
虚函数
- 解决问题:通过基类指针只能访问派生类的成员变量,但是不能访问派生类的成员函数的问题
- 纯虚函数:
- 纯虚函数是在声明虚函数时被“初始化”为0的函数。
- 声明格式:virtual 函数类型 函数名 (参数表列) =0;
注意:
①纯虚函数没有函数体;
②最后面的“=0”并不表示函数返回值为0,它只起形式上的作用,告诉编译系统“这是纯虚函数”;
③这是一个声明语句,最后应有分号。
④纯虚函数只有函数的名字而不具备函数的功能,不能被调用。它只是通知编译系统: “在这里声明一个虚函数,留待派生类中定义”。在派生类中对此函数提供定义后,它才能具备函数的功能,可被调用。
模板
自定义栈类
#include <iostream>
using namespace std;
const int Max_SIZE=100;//定义栈大小
class Stack
{
public:
Stack();
~Stack();
void Push(int x);//入栈
void Pop();//出栈
int GetTop();//取栈顶元素
bool IsEmpty();//判空
bool IsFull();//判满
int GetSize();//取栈中元素个数
private:
int *data;
int top;//栈顶标记位
};
Stack::Stack()
{
top=0;
data=new int [Max_SIZE];
}
Stack::~Stack()
{
delete [] data;
}
bool Stack::IsFull()
{
if(top>=Max_SIZE) return true;
else return false;
}
bool Stack::IsEmpty()
{
if(top==0) return true;
else return false;
}
void Stack::Push(int x)
{
if(!IsFull())
{
data[top++]=x;
}
else
{
cout<<"Stack is Full!"<<endl;
}
}
void Stack::Pop()
{
if(!IsEmpty())
{
top--;//移动栈顶即可
}
else
{
cout<<"Stack is Empty!"<<endl;
}
}
int Stack::GetTop()
{
return data[top-1];
}
int Stack::GetSize()
{
return top;
}
int main()
{
Stack s;
int a,n;
cout<<"元素入栈(用空格分隔),输入-1结束:";
while(!s.IsFull())
{
cin>>n;
if(n==-1) break;
else s.Push(n);
}
cout<<"栈中元素个数:";
cout<<s.GetSize()<<endl;
cout<<"栈中元素出栈:";
while(!s.IsEmpty())
{
a=s.GetTop();
s.Pop();
cout<<a<<" ";
}
cout<<endl<<endl;
return 0;
}