码迷,mamicode.com
首页 > 编程语言 > 详细

浅析c++面向对象特性

时间:2018-08-15 21:35:31      阅读:168      评论:0      收藏:0      [点我收藏+]

标签:tab   构造   功能   自己的   相同   获得   pos   lsp   height   

2018-08-15  20:17:14

1、三大特性

所谓封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。封装是面向对象的特征之一,是对象和类概念的主要特性。 简单的说,一个类就是一个封装了数据以及操作这些数据的代码的逻辑实体。在一个对象内部,某些代码或某些数据可以是私有的,不能被外界访问。通过这种方式,对象对内部数据提供了不同级别的保护,以防止程序中无关的部分意外的改变或错误的使用了对象的私有部分。

class Student
{
public:
   Student(string _name):name(_name){} 
   void hello();     
protected(or private):
   string name; 
};

上面实现了一个简单的类,其中有公共的一些接口,即public修饰的hello函数,以及由protected或者private修饰的类成员变量,它们是只可以由类内的成员函数访问,尽管由外部实现了的类也不能直接通过成员操作符或者指针访问和修改。这里可以保证类里

的数据可以得到充分的保护。


所谓继承是指可以让某个类型的对象获得另一个类型的对象的属性的方法。它支持按级分类的概念。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。 通过继承创建的新类称为“子类”或“派生类”,被继承的类称为“基类”、“父类”或“超类”。继承的过程,就是从一般到特殊的过程。要实现继承,可以通过“继承”(Inheritance)和“组合”(Composition)来实现。继承概念的实现方式有二类:实现继承与接口继承。实现继承是指直接使用基类的属性和方法而无需额外编码的能力;接口继承是指仅使用属性和方法的名称、但是子类必须提供实现的能力;

不同的继承类型带来的效果
  继承方式 public protected private
父类中的public public protected private
父类中的protected protected protected private
父类中的private private private private

不同的继承方式使得父类在子类中的访问权限不同,既是对父类的保护,也能提高代码复用,减轻程序的工作量。

所谓多态就是指一个类实例的相同方法在不同情形有不同表现形式。多态机制使具有不同内部结构的对象可以共享相同的外部接口。这意味着,虽然针对不同对象的具体操作不同,但通过一个公共的类,它们(那些操作)可以通过相同的方式予以调用。

这里首先要介绍一下多态里用到的virtual修饰符,由于在继承的过程中,父类的所有成员都被继承到了子类当中,因此操作系统在分配的内存的时候会重复地给父类的成员变量分配内存空间,并且在实例化子类的时候父类的构造函数和析构函数也将多次调用,导致了内存的浪费,通过在继承的时候加入virtual声明继承方式,能够只在内存保留一份父类的副本。说到这里,回到多态,也是相似的原理:通过将父类的成员函数声明为virtual,从而在多个子类继承的时候,能够通过动态联接找到应该指向的子类方法。

引用:在C++中通过虚函数表的方式实现多态,每个包含虚函数的类都具有一个虚函数表(virtual table),在这个类对象的地址空间的最靠前的位置存有指向虚函数表的指针。在虚函数表中,按照声明顺序依次排列所有的虚函数。实例化一个对象时调用完构造函数后,便会初始化这些指针。由于C++在运行时并不维护类型信息,所以在编译时直接在子类的虚函数表中将被子类重写的方法替换掉。当程序中将要调用一个虚函数时,编译器会编译成从指针中找到具体的实现函数。因为虚函数指针在对象实例化时就被初始化了,所以即便是该对象被一个父类指针指向也能找到正确的函数。

另外,一日为虚终生为虚。一个函数被声明为虚时,其衍生类的该函数也将一直是虚函数,即使衍生类没有显式声明为virtual。

class Base_class
{
public:

    Base_class(string _name):name(_name)
    {
        cout<<"this is constructor"<<endl;
    }
//    ~Base_class()
//    {
//        cout<<"this is destructor"<<endl;
//    }
    virtual void say_hi(int) const =0;

protected:
    string name;
};

class sub_class:public Base_class
{
public:
    sub_class(string _name,int _sex):sex(_sex),Base_class(_name){}
    void say_hi(int) const;
private:
    int sex;
};

class sub_class_:public Base_class
{
public:
    sub_class_(string _name,int _score):score(_score),Base_class(_name){}
    void say_hi(int ) const;
private:
    int score;
};

void sub_class::say_hi(int num) const
{
    cout<<"sex:"<<sex<<endl;
}

void sub_class_::say_hi(int num) const
{
    cout<<"score: "<<score<<endl;
}
int main()
{
    Base_class *s = new sub_class("wang",1);
    Base_class *s1 = new sub_class_("Li",2);
    s->say_hi(2);
    s1->say_hi(3);
    delete s;
    delete s1;
    return 0;
}

 

上述是两个子类对父类纯虚函数的重写,注意到主函数里两个指针的类型均为基类类型,此时访问say_hi方法是能够正确找到子类重写的方法的,当然,有人问为什么不直接用子类定义呢,这里只是两个指针,使用new产生对象,如果存在了大量的实例化的情况,是可以通过同一指针不同的指向来节省程序员命名变量的数量。

总结:以上是目前学习完《c++程序设计》这本书的基础认识,之后有新的体会也会继续增加内容。如有错误,还望斧正!

 

浅析c++面向对象特性

标签:tab   构造   功能   自己的   相同   获得   pos   lsp   height   

原文地址:https://www.cnblogs.com/jianbo1995/p/9484062.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!