类与对象
定义类
class 类名{
private:
变量或函数
protected:
变量或函数
public:
变量或函数
};
private定义私有成员,外部不能调用。
public定义共有成员,外部直接调用,是内部与外部的接口。
protected定义保护成员,外部不能直接调用,但是派生类可以使用。
eg:
class person{
private:
sting name;
char sex;
int age;
public:
void getin()//输入接口
void printp()//输出接口
};
定义成员函数
void person::getin()
{
cin>>name;
cin>>sex;
cin>>age;
}
成员函数之前一定要加上类名和::,以此来区分是哪个类的成员;
对象
对象是类的实例
person p1,p2;
定义p1p2两个对象。
还可以定义对象的指针。
person *p;
然后就可以对对象进行操作了
int main()
{
person *p,p1,p2;
p1.getin();//不能对name等private变量直接赋值,只能对private的函数或变量进行操作。
p2.getin();
p=&p1;//指针指向p1;
p->printp();//相当于p1.printp();
}
this指针
系统在编译类时,自动创建this指针指向对象。
当成员的名字和参数名字相同时,还可以区分二者。
eg:
void getinsex(char sex)
{
this->sex = sex;
}
构造函数
构造函数没有返回值,不能加void,也没有return;
在声明对象时,构造函数自动执行。(据我的理解,这个函数的功能类似初始化)
构造函数应放在public中,因为其是在类外使用。
eg:
class mycomplex{
private:
int x,y;
public:
mycomplex(int a,int b);
mycomplex();
};
mycomplex::mycomplex(int a,int b)
{
x=a;
y=b;
}
mycomplex::mycomplex(int a,int b) : x(a),y(b)//一种神奇的赋值方式
{
}
mycomplex::mycomplex()//没有参数也可以
{
x=0;
y=0;
}
构造函数的重载
eg:
class mycomplex{
private:
int x,y;
public:
mycomplex(int a,int b);
};
mycomplex::mycomplex(int a,int b)
{
x=a;
y=b;
}
对于这个类,调用时如下
int main()
{
mycomplex mm(1,2);
}
析构函数
作用是释放对象所占的空间,生命周期结束时自动被调用。
函数名是类名前加上~.
必须放在public里面。
eg:
class person{
public:
~person()
{ cout<<"Destroying";}
};
堆对象
静态数据成员
不管一个类的对象有多少个,其静态数据成员也只有一个,由这些对象所共享,可被任何一个对象访问。
class visitor{
private:
char *name;
public:
static int count;
};
友元和友元类
允许友元和友元类访问类的私有成员和保护成员的辅助方法。
友元函数eg:
class ss{
private:
int x;
public:
friend void sum(ss &a);
};
void sum(ss &a)
{
cout<<a.x;
}
友元类eg:
class A
{
friend class B;
};
继承和派生类
继承
继承就是利用原有的类定义新的类。
基类和派生类
通过继承,派生类拥有的基类原有的数据类型,还可以添加新的数据类型。
也就是当我们拥有一个定义好的类之后,可以对其进行拓展,添加新的成员,使其变成新的派生类。
单继承
派生类只有一个直接基类
class 派生类名:继承方式 基类名
{ 派生类中的新成员 };
从基类继承全部数据成员和成员函数
由派生类定义时的继承方式来控制基类成员的访问方式。(重名覆盖)
添加新成员
基类中的私有成员和不可访问成员在派生类中不可访问。
eg:
class base//基类
{
private:
int a;
protected:
int b;
public:
int c;
void set(int k) { a=k;}
};
class deri : public base//派生类
{
public:
void set() { c=0;}
};
int main()
{
deri d;
d.set();
}
函数重写:基类已经定义的成员函数,在派生类中重新定义。
此时,基类中该成员函数的其他重载函数被屏蔽,可以在派生类中通过using 类名::成员函数名 恢复。
#include <iostream>
using namespace std;
class T {};
class B {
public:
void f() { cout << "B::f()\n"; }
void f(int i) { cout << "B::f(" << i << ")\n"; }
void f(double d) { cout << "B::f(" << d << ")\n"; }
void f(T) { cout << "B::f(T)\n"; }
};
class D1 : public B {
public:
using B::f;
void f(int i) { cout << "D1::f(" << i << ")\n"; }
};
int main() {
D1 d;
d.f(10);//D1::f(10)
d.f(4.9); //B::f(4.9)
d.f(); //B::f()
d.f(T()); //B::f(T)
return 0;
多重继承
派生类同时由多个直接基类
class 派生类名: 继承方式 基类名1, 继承方式 基类名2...
class D:public A, public B
{};
多重继承存在二义性:
多个基类有同名的成员。应使用限定名来访问基类的同名成员。
class D:public B1, public B2
{
private:
int dv;
public:
D();
D(int v1, int v2, int v3);
~D();
void Show();
};
D::D():dv(0)
{ cout<<"D()\n"; }
D::D(int v1, int v2, int v3):B1(v1), B2(v2), dv(v3)
{ cout<<"D(int, int, int)\n"; }
D::~D()
{ cout<<"~D()\n"; }
void D::Show()
{
cout<<"B1(av="<<B1::av<<" bv="<<B1::bv<<") ";
cout<<"B2(av="<<B2::av<<" bv="<<B2::bv<<") ";
cout<<"dv="<<dv<<endl;
}
多个基类具有一个共同的基类(祖先类)
eg:
这时应将祖先类设置为虚基类
class A
{ … }
class B1 : virtual public A
{ … }
class B1 : virtual public A
{ … }
Class D : public B1, public B2
{ … }
赋值兼容规则
虚函数
class 类名
{
virtual 类型 函数名(参数表);
}
class A
{
public:
virtual void Show()
{
cout<<"A::Show()\n";
}
};
class B1 : public A
{
};
class B2 : public A
{
public:
void Show()
{
cout<<"B2::Show()\n";
}
};
class D : public B1
{
public:
void Show()
{
cout<<"D::Show()\n";
}
};
void main()
{
A *pa;
B1 b1;
B2 b2;
D d;
pa = &b1;
pa->Show();//A::Show()
pa = &b2;
pa->Show();//B2::Show()
pa = &d;
pa->Show();//D::Show()
}
纯虚函数
virtual 函数原型 = 0;
纯虚函数没有函数体。
抽象类
class Shape
{
public:
virtual void Show()=0;
virtual double Area()=0;
};