C++学习笔记2--面向对象

来源:互联网 发布:php源码详细安装步骤 编辑:程序博客网 时间:2024/06/06 01:37
类的声明格式:
class 类名标识符{[public:][数据成员的声明][成员函数的声明][private:][数据成员的声明][成员函数的声明][protected:][数据成员的声明][成员函数的声明]};

【类的实现】
第一种方法是将类的成员都定义在类体内。
第二种方法,也可以将类体内的成员函数的实现放在类体外,但如果类成员定义在类体外,需要用到域运算符“::”,放在类体内和类体外的效果是一样的。
C++语言可以实现将函数的声明和函数的定义放在不同的文件,一般在头文件放入函数的声明,在实现文件放入函数的实现。可将类的定义放在头文件中,将类成员变量放在实现文件内。
【构造函数】
类的构造方法:
class CPerson {public:    CPerson();    int m_iIndex;    int getIndex();};//构造函数CPerson::CPerson() {    m_iIndex = 10;}


CPerson()是CPerson的默认构造方法,构造方法可以定义为带参的。
【复制构造函数】
复制构造函数就是函数的参数是一个已经初始化的类对象。
范例:
#include <iostream>#include <cstring>using namespace std;class Person {public:    Person(int _index, char *_name); //构造函数    Person(Person & copyPerson); //复制构造函数    int index;    char name[30];};//构造函数Person::Person(int _index, char *_name) {    index = _index;    strcpy(name, _name);}//复制构造函数Person::Person(Person & copyPerson) {    index = copyPerson.index;    strcpy(name, copyPerson.name);}int main(int argc, char *argv[]) {    Person p(1, "lasolmi");    Person q(p);    cout << q.name << endl;    return 0;}


【析构函数】
构造函数主要用来在对象创建时,给对象中的一些数据成员赋值,主要目的就是来初始化对象。
析构函数的功能是用来释放一个对象的,在对象删除前,用它来做一些清理工作,它与构造函数的功能正好相反。
CPerson::~CPerson() {    delete[] m_pMessage;}


【类成员】
public属性的成员对外可见,对内可见。
private属性的成员对外不可见,对内可见。
protected属性的成员对外不可见,对内可见,且对派生类是可见的。
在默认情况下,类成员的属性为private。
【内联成员函数】
类内(类内默认inline)声明:inline char* GetUsername() const;
类外直接定义:inline char* CUser::GetUsername() const {...}
【静态类成员】
静态类成员在类成员定义前使用static关键字标识。例如:
class CBook {public:    static unsigned int m_Price;};在定义静态数据成员时,通常需要在类体外部对静态成员进行初始化。例如:unsigned int CBook::m_Price = 10;对于静态成员来说,不仅可以通过对象访问,还可以直接使用类名访问。例如:int main(int argc,char* argv[]) {    CBook book;    cout << CBook::m_Price << endl; //通过类名访问静态成员    cout << book.m_Price << endl; //通过对象访问静态成员    return 0;}


静态数据成员可以是当前类的类型,而其他数据成员只能是当前类的指针或引用类型。
例:
class CBook {public:    static unsigned int m_Price;    CBook m_book;           //非法的定义,不允许在该类中定义所属类的对象    static CBook m_VCbook;  //正确,静态数据成员允许定义类的所属类对象    CBook *m_pBook;         //正确,允许定义类的所属类型的指针类型对象}


静态数据成员可以作为成员函数的默认参数。
静态成员函数的丁一部分写在类外时无需加static。
C++类中藏有this指针。
【嵌套类】
范例:在定义CList类时,在内部定义了一个嵌套类CNode。
#include <iostream>#include <cstring>using namespace std;#define MAXLEN 128class CList {public:    class CNode {        friend class CList;    private:        int m_Tag;    public:        char m_Name[MAXLEN];    };public:    CNode m_Node;    void SetNodeName(const char *pchData) {        if(pchData != NULL) {            strcpy(m_Node.m_Name, pchData);        }    }    void SetNodeTag(int tag) {        m_Node.m_Tag = tag;    }};int main(int argc, char* argv[]) {    CList c;    c.SetNodeName("lasolmi");    cout << c.m_Node.m_Name << endl;    return 0;}


上述代码在嵌套类CNode中定义了一个私有成员m_Tag,定义了一个公有成员m_Name,对于外围类CList来说,通常他不能访问嵌套类的私有成员,虽然嵌套类是在其内部定义的。但是,上述代码在定义CNode类时将CList类作为自己的友元类,这使得CList类能够访问CNode类的私有成员。
对于内部的嵌套类来说,只允许其在外围的类域中使用,在其他类域或者作用域中是不可见的。
可以采用下述方法调用:
CList::CNode node;
局部类:类的定义放置在函数中。
【友元】friend
友元类:
class B {public:    friend class A;    ...}

友元方法:
class B {    friend void A::function();    ...};

对于由原函数来说,不仅可以是类的成员函数,还可以是一个全局函数。
class B {    friend void function();    ...}void function() {...}

【命名空间】
命名空间的定义格式为:
namespace 名称{    常量、变量、函数等对象的定义}

引用空间成员的一般形式为是:
命名空间名称::成员;
例:定义命名空间
#include <iostream>using namespace std;namespace MyName1 { //定义命名空间    int iValue = 10;}namespace MyName2 { //定义命名空间    int iValue = 20;}int iValue = 30; //全局变量int main(int argc,char* argv[]) {    cout << MyName1::iValue << endl; //引用MyName1命名空间中的变量    cout << MyName2::iValue << endl; //引用MyName2命名空间中的变量    cout << iValue << endl;    return 0;}

另一种引用命名空间中成员的方法:使用using namespace语句。一般形式为:
using namespace 命名空间名称;
如果使用using namespace语句,则在引用空间中的成员时直接使用就可以。
例:定义嵌套的命名空间。
#include <iostream>using namespace std;namespace Output {    void show() {        cout << "Output's function!" << endl;    }    namespace MyName {        void Demo() {            cout << "MyName's function!" << endl;        }    }}int main(int argc, char* argv[]) {    Output::show();    Output::MyName::Demo();    return 0;}

【继承】
类继承的形式如下:
class 派生类名标识符:[继承方式] 基类名标识符 {    [访问控制修饰符:]    [成员声明列表]}

继承方式有3种派生类型:public,protected,private.
 public(共有型派生):共有型派生表示对于基类中的public数据成员和成员函数,在派生类中仍然是public,对于基类中的private数据成员和成员函数,在派生类中仍然是private。
 private(私有型派生):私有型派生表示对于基类中的public、protected数据成员和成员函数,在派生类中可以访问。基类中的private数据成员,在派生类中不可以访问。
 protected(保护型派生):保护型派生表示对于基类中的public、protected数据成员和成员函数,在派生类中均为protected。protected类型在派生类定义时可以访问,用派生类声明的对象不可以访问,也就是说在类体外不可以访问。protected成员可以被基类的所有派生类使用。这一性质可以沿继承树无限向下传播。
【子类隐藏父类的成员函数】
设B类是A类的派生类,A中存在方法function(),B中也存在方法function(),则B类成员b使用自身function()方法为:
b.function();
子类使用父类function()方法为:
b.A::function();
【重载运算符】
重载运算符的声明形式:
operator 类型名();
不允许重载的运算符:“.”、“*”、“::”、“?”、“:”。
例:通过重载运算符实现求和
#include <iostream>using namespace std;class CBook {public:    CBook(int iPage) {        m_iPage = iPage;    }    CBook operator+(CBook b) {        return CBook(m_iPage+b.m_iPage);    }    void display() {        cout << m_iPage <<endl;    }protected:    int m_iPage;};int main(int argc,char* argv[]) {    CBook bk1(10);    CBook bk2(20);    CBook tmp(0);    tmp = bk1 + bk2;    tmp.display();    return 0;}

【多重继承】
C++支持多重继承。多重继承是指有多个基类名标识符,其声明形式如下:
class 派生类名标识符:[继承方式] 基类名标识符1,...,访问控制修饰符 基类名标识符n{    [访问控制修饰符:]    [成员声明列表]};

范例:鸟能够在天空飞翔,与能够在水里游,而水鸟既能够在天空飞翔,又能够在水里游。那么在定义水鸟类时,可以将鸟和鱼同时作为其基类。
#include <iostream>using namespace std;class CBird {public:    void FlyInSky() {        cout << "鸟能够在天空飞翔" << endl;    }    void Breath() {        cout << "鸟能够呼吸" << endl;    }};class CFish {public:    void SwimInWater() {        cout << "鱼能够在水里游" << endl;    }    void Breath() {        cout << "鱼能够呼吸" << endl;    }};class CWaterBird: public CBird, public CFish {public:    void Action() {        cout << "水鸟能飞又能游" << endl;    }};int main(int argc, char* argv[]) {    CWaterBird waterbird;    waterbird.FlyInSky();    waterbird.SwimInWater();    return 0;}

当要用到Breath()方法,可以这么办:
waterbird.CFish::Breath(); //调用CFish类的Breath成员函数
waterbird.CBird::Breath(); //调用CBird类的Breath成员函er数
二义性:当派生类的两个或多个父类中都含有function函数,派生类将不知道调用哪个function成员函数,这就产生了二义性。
多重继承的构造函数被调用的顺序以类派生表中生命的顺序为准。派生表就是多重继承定义中继承方式后面的内容,调用顺序就是按照基类名标识符的前后顺序进行的。
【多态】
C++语言中,多态指:具有不同功能的函数可以用同一个函数名。
多态性通过联编实现。联编指计算机程序彼此关联的过程。
联编按进行的阶段不同分为:静态联编 和 动态联编。
C++中,按联编的时刻不同,存在两种类型多态性:函数重载 和 虚函数。
在基类中用virtual声明成员函数为虚函数。
覆盖和重载的区别是:重载是同一层次函数名相同,覆盖是在继承层次中成员函数的函数原型完全相同。
例:利用虚函数实现动态绑定
#include <iostream>#include <cstring>using namespace std;class CEmployee {   //定义CEmployee类public:    int m_ID;    char m_Name[128];    char m_Depart[128];    CEmployee() {        memset(m_Name, 0, 128);        memset(m_Depart, 0, 128);    }    virtual void OutputName() {     //定义一个虚成员函数        cout << "员工姓名:" << m_Name << endl;    }};class COperator:public CEmployee {  //从CEmployee类派生一个子类public:    char m_Password[128];    void OutputName() {        cout << "操作员姓名:" << m_Name << endl;    }};int main(int argc, char* argv[]) {    CEmployee *pWorker = new COperator(); //定义CEmployee类型指针,调用COperator类构造函数    strcpy(pWorker->m_Name, "lasolmi");   //设置m_Name数据成员信息    pWorker->OutputName();                //调用COperator类的OutputName成员函数    delete pWorker;                       //释放对象    return 0;}

虚函数有以下几方面限制:
(1)只有类的成员函数才能为虚函数。
(2)静态成员函数不能为虚函数,因为静态成员函数不受限于某个对象。
(3)内联函数不能是虚函数,因为内联函数是不能在运行中动态确定其位置的。
(4)构造函数不能使虚函数,析构函数通常是虚函数。
从CBird类和CFish类派生子类CWaterBird类时,在CWaterBird类中将存在两个CAnimal类的复制。那么如何在派生CWaterBird类时使其只存在一个CAnimal基类呢?C++语言提供的徐继承机制,解决了这个问题。
例:虚继承
#include <iostream>using namespace std;class CAnimal { //定义一个动物类public:    CAnimal() {cout<<"动物类被构造"<<endl;}    void move() {cout<<"动物能够移动"<<endl;}};class CBird : virtual public CAnimal { //从CAnimal类虚继承CBird类public:    CBird() {cout<<"鸟类被构造"<<endl;}    void FlyInSky() {cout<<"鸟能够在天空飞翔"<<endl;}    void Breath() {cout<<"鸟能够呼吸"<<endl;}};class CFish : virtual public CAnimal { //从CAnimal类虚继承CFish类public:    CFish() {cout<<"鱼类被构造"<<endl;}    void SwimInWater() {cout<<"鱼能够在水里游"<<endl;}    void Breath() {cout<<"与能够在水里游"<<endl;}};class CWaterBird : public CBird,public CFish {public:    CWaterBird() {cout<<"水鸟类被构造"<<endl;}    void Action() {cout<<"水鸟既能飞又能游"<<endl;}};int main(int argc,char* argv[]) {    CWaterBird waterbird;    return 0;}

输出结果为:
动物类被构造
鸟类被构造
鱼类被构造
水鸟类被构造
【抽象类】
包含至少一个纯虚函数的类称为抽象类。
抽象类只能作为基类用来派生出新的子类,而不能在程序中实例化(即不能说明抽象类的对象),但是可以使用指向抽象类的指针。
纯虚函数(Pure Vitual Function):指被标明为不具体实现的虚成员函数,它不具备函数功能。
虚函数不能被直接调用,仅起到提供一个与派生类相一致的接口的作用。
声明虚函数的形式为:
virtual 类型 函数名(参数表列)=0;
实现抽象类中的成员函数:抽象类通常用于作为其他类的父类,从抽象类派生的子类如果是抽象类,则子类必须实现父类中的所有纯虚函数。
例:实现抽象类中的成员函数
#include <iostream>#include <cstring>using namespace std;class CEmployee { //定义CEmployee类public:    int m_ID;    char m_Name[128];    char m_Depart[128];    virtual void OutputName()=0; //定义抽象成员函数};class COperator : public CEmployee {public:    char m_Password[128];    void OutputName() {cout<<"操作员姓名:"<<m_Name<<endl;}    COperator() {strcpy(m_Name, "lasolmi");}};class CSystemManager : public CEmployee { //定义CSystemManager类public:    char m_Password[128];    void OutputName() {cout<<"系统管理员姓名:"<<m_Name<<endl;}    CSystemManager() {strcpy(m_Name, "congli");}};int main(int argc, char* argv[]) {    CEmployee *pWorker;         //定义CEmployee类型指针    pWorker = new COperator();  //调用COperator类的构造函数,为pWorker赋值    pWorker->OutputName();      //调用COperator类的OutputName成员函数    delete pWorker;             //释放pWorker对象    pWorker = NULL;             //将pWorker对象设置为空    pWorker = new CSystemManager();  //调CSystemManager用类的构造函数,为pWorker赋值    pWorker->OutputName();      //调用CSystenManager类的OutputName成员函数    delete pWorker;             //释放pWorker对象    pWorker = NULL;             //将pWorker对象设置为空    return 0;}


0 0
原创粉丝点击