您的位置:首页 > 编程语言 > C语言/C++

C/C++软件工程师就业求职手册学习笔记---第八章

2014-04-03 14:33 288 查看

第八章 面向对象

面向对象主要包括:
1、类,具有相似的内部状态和运动规律的实体的集合。
2、对象,类的实例,也是现实世界各种各样的实体。
3、消息,消息主要包括五部分,消息的发送对象,消息的接受对象,消息的内容,消息的传递方法,反馈。
4、类的特性,抽象、继承、多态、封装、重载。
C语言是以过程式语言,以过程为中心,以算法为驱动。C++ 是以面向对象为中心,以消息为驱动。
例子1:
struct 和class的区别:
1、对于c语言中的struct,只能够定义一种数据类型,不能定义成员函数。
2、在C++中,struct的默认定义方式为public,继承方式也只能是public,而class则不是。
3、class还可以用模板类型,而struct则不行。


#definepublic private //居然是对的!!



例子2:
成员初始化:类中成员初始化顺序是按照定义顺序初始化的。

类中的static类型属于类本身,被类的各个对象所共享,而非static类型成员在每个对象中都自己的复制品。
静态成员的优势:
1、静态成员没有进入全局命名空间,所以不会存与程序中其他全局明冲突
2、静态成员是私有的,而全局对象不能。

例子3:什么情况下只能用初始化列表,不能用赋值。
1、对于const类型成员,只能用初始化列表;对于父类的私有成员,不能直接赋值初始化,也不能调用其构造函数初始化,只能用初始化列表。
2、static成员不能再在类内利用赋值或者初始化列表初始化,只有静态常量才可以在类内赋值初始化,static const int a=4;
3、静态成员函数只能调用静态成员,不能调用非静态成员,这是因为静态成员不属于类的对象,因此就没有this指针,也就找不到非静态成员。

注意:全局对象的构造函数在main函数之前被调用!
例子4:
对于一个C++空类,编译器会加入:
1、构造函数和复制构造函数,用于类的对象的构造过程。
2、析构函数,用于类的对象的析构过程
3、赋值函数,用于同类间的赋值过程。
4、取值函数,当类的对象进行取地址(&)时,此函数被调用。
所以一个空类如下:

class empty
{
         public:
                  empty();
                  empty(const empty &);
                  ~empty();
                  const empty&operator=(const empty &);
                  const empty* operator&()const;
                  empty *operator&();              
}



构造函数内调用构造函数,只是在函数内部产生一个临时对象,对其毫无影响。构造函数互相调用引起的后果不是死循环,而是栈溢出。
explicit声明的函数只能被显示调用,不能够隐式调用。

class test1
{
         public:
            int m;
                  test1(int a)
                  {
                          m=a;
                  }
                  ~test1();
};
class test2
{
         public:
           int m;
           explicit test2(int a )
           {
                          m=a;
           }
           ~test2();
}
int main()
{
         test1 t1=12;//correct
         test2 t2=12;//error
         test2 t3(12);
return 0;
}
 
class haha
{
public:
         string s;
         explicithaha(int):s("int"){};
         explicithaha(short):s("short"){};
         haha(char):s("char"){};
         //void show(const haha& n);
        
};
void show(const haha& n)
{
         cout<<n.s<<endl;
}
 
voidmain()
{
         short s=42;
         show(s);
}


由于show函数的形参是haha类,所以传入s后,会调用构造函数生成临时对象,而对应short型的构造函数要求必须要显示调用,不能隐式转换,所以只能讲s进行类型转换,寻找其他构造函数,如果我们将三个构造函数均声明为explicit,那么临时对象将不能生成,就会报错。

例子5:C++中的虚函数:
1、虚函数是C++多态性的重要特征,类中的虚函数可以在类的对象中重新实现(如果未重新定义,则直接继承父类),其在类中声明为virtual,则默认在对象中仍为virtual类型,习惯上在类的对象中继续使用virtual,并且需要保证函数名,参数类型、名称、个数完全相同。
2、默认的都是非虚函数,要进行动态绑定,需要两个条件一个是,成员函数指定为virtual类型,二是通过基类的指针或者引用调用。
3、在对象中,重新实现虚函数时,如需要调用基类中的同名虚函数,需要指定作用域,否则则会调用自身,导致栈溢出。
4、对于非虚函数,基类指针或引用只能调用基类成员函数,对象或继承类的指针或引用只能调用对象或继承类的成员函数,不满足多态性的要求。而virtual类型成员函数可以满足,利用基类指针或引用可以调用基类对象成员函数或是基类对应子类的成员函数,这样就实现了多态性。
5、对于基类指针或引用调用对象或继承类对象初始化后,在删除对象时,如果析构函数没有定义为virtual,则基类指针或引用只能调用基类的析构函数,这样就无法删除对象特有的那部分数据,导致内存泄露。
6、由于定义为virtual类型,会增大对象的占用空间,所以并不是什么情况都定为virtual最好。原则上,当类中至少含有一个virtual成员函数时,将析构函数定义为virtual类型。
7、不要再构造函数或析构函数中调用虚函数
8、当一个函数被用作基类时,才会把析构函数写成虚函数。

例子6:复制构造函数:
复制构造函数是一种特殊的构造函数,用同类型的对象初始化,如果没有显示的定义复制构造函数,编译器会默认生成一个位复制构造函数。
在C++中,三种对象需要复制,此时复制构造函数会被调用
1、对象以值传递的方式传入函数体的。
2、一个对象以值传递的方式从函数体返回的;
3、一个对象需要另一个对象初始化的。

class haha
{
public:
         int a;
         haha(int c):a(c){};
         haha(haha &t)
         {
                  a=t.a;
                  cout<<"copy"<<endl;
         }
         void  f1(haha h)
         {
                  cout<<"f1"<<endl;
         }
         haha f2()
         {
                  haha h(2);
                  return h;
         }      
};
void main()
{
    haha h1(2);
         haha h2=h1;// copy
         h1.f1(h2);//copy  f1
         h1.f2();//copy
         haha h3=h1.f2();//copy
}


例子 7:深复制,浅复制:
如果复制的对象中引用了某个外部的内容(例如分配在堆上的数据),那么在复制这个对象的时候,让新旧两个对象指向同一个外部内容,就是浅复制。如果再复制这个对象的时候为新对象只做了外部对象的独立复制,那就是深复制。

如果用户没有定义复制构造函数,那么编译器会自动生成一个;如果用户定义了编译器就不会再生成。
复制构造函数和赋值构造函数的区别:
1、赋值构造函数,是对已经被初始化的对象进行赋值操作,而复制构造函数是用一个对象去初始化另一个对象。
2、实现不一样。复制构造函数首先是构造函数,它通过参数的对象产生一个对象,而赋值构造函数则是把一个新的对象赋值给原有的对象。如果原来对象有内存分配,则需要释放掉,而且要检查两个对象是否是同一个对象。
3、一般来说,在数据成员中包含指针对象的时候,应考虑两种不同需求:一种是复制指针对象,另一种是引用指针对象。复制构造函数大多时候是复制,而赋值构造函数则是引用对象。

临时变量会影响效率,尽量用引用传递代替值传递。

例子8:什么是函数重载?为什么C没有?
函数重载是用来描述同名函数具有相同功能或相似功能,但数据类型或者参数不同的管理操作。
C++中,函数编译后会将参数信息加入到函数名中,用以区分不同函数,而C不支持这一操作。

例子 9:重载和覆写区别:
重载特征:同一函数不同版本之间参数不同,方法名相同,但是参数列表不同,与参数列表顺序无关。返回值类型可以不同。
覆写特征:是子类改写父类方法。只有虚方法和抽象方法可以被覆写。具有相同的函数名,具有相同的参数列表,具有相同的返回值。
重载是一种语法规则,在编译阶段完成,不属于面向对象编程。而覆写是在程序运行阶段完成的,是面向对象的重要特征。
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
string 类实现,后面补上。
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: