C++ 笔记

C++笔记

1

推动语言发展的动力是方便和重用

不是只有面向对象语言可以封装,C语言也可以封装,结构体成员是函数指针的时候也是满足的,但是比较麻烦。

 

2类的定义

类名首字母大写;

方法名首字母小写

Class 类名

{     private:

 

      public:

};

 

3定义成员函数(调用成员函数时必须指定对象和成员名)

(1)在类中定义成员函数

类中定义的成员函数一般为内联函数,即使没有明确用

inline标示;

在C++中,类定义通常在头文件中,因此这些成员函数

定义也伴随着进入头文件;

 

(2) 在类之后定义成员函数

                     C++允许在其它地方定义成员函数;

将类定义和其成员函数定义分开,是目前开发程序的

通常做法。

我们把类定义看成是类的外部接口,类的成员函数定

义看成是类的内部实现。

(3)类成员函数的重载

重载的定义:两个以上的函数,取相同的函数名,但是形参的个数或者类型不同,编译器根据实参和形参的类型及个数的最佳匹配,自动确定调用哪个函数。

类的成员函数可以像普通函数一样重载,但是不同类即使有相同的函数名也不算重载。

4成员函数外部定义的格式

返回类型  类名::函数名(参数1,参数2……)

5类的成员的访问

不管怎么继承,父类私有东西是不能访问的

1单个类

类成员可以访问所有;

单个类实例化对象只能访问共有域public

2继承

派生类可以访问父类的public and protected;

Public继承父类的protected and public 在子类中不变;

私有继承,父类的protected and public在子类中转换成私有域;

3保护继承

父类的protected and public全部转换为protected域;

多继承只在c++

成员访问

(1) 如果是私有的,外部全部不能访问;

(2) 如果是公有的,普通对象:对象名.成员

指针对象:对象名->成员

(3) 静态成员或方法

   Const不可更改可以直接赋值;公有的,类名::静态成员

(4) 在类中静态成员拥有者是类,静态成员将会只有一个父本

6

构造函数的要求:

(1)函数名必须与类名同名

(2)构造函数可重载;

(3)类实例化后系统会自动调用。

(4)构造函数无返回类型

(5)构造函数不能被用户调用,只能被系统调用;只能在实例化的时候定义;

(6)如果不写构造函数编译器会自动添加一个无參的构造函数。一旦你写了构造 函数,系统将不会给他添加

 

7

析构函数:释放内存空间

(1)没有返回类型,没有参数,不能随意调用,没有重载。只有在类生命期结束的时候,有系统调用。

(2)析构函数名,就在构造函数名前加上一个“~”,表示“逆构造函数”。

8

堆空间

(1)new:分配堆空间和delete配套使用:释放堆空间。

(2)new一个对象会自动调用构造函数,delete一个对象会自动调用析构函数,new和delete不需要头文件。

(3)从堆中分配对象数组:类名 *ps = new 类名[int n];

(4)释放一个对象数组:delete[]ps;

(5)使用堆空间的原因:直到运行时才能知道需要多少对象空间;不知道对象的生存期到底有多长;知道运行时才知道一个对象需要多少内存空间。

9

构造对象的顺序

(1)局部和静态对象,以声明的顺序构造;

(2)静态对象只被构造一次

(3)所有全局对象都在主函数main()之前被构造

(4)全局对象构造时无特殊顺序

(5)成员以其在类中声明的顺序构造

Class     SA{};

SA ();无名对象创建之后就会被释放;

SA  h; 执行到最后才会被释放。

对于全局对象,是在main函数执行之前调用构造函数的。

10

赋值格式:

类型  类名::静态名 = a;

静态方法只能访问静态成员,因为他没有this指针。

New兼容malloc的功能。

11

拷贝构造函数:

(1)可用一个对象去构造另一个对象

(2)对象作为函数参数传递时,也要涉及对象的拷贝

(3)class  Stu{;;};

(4)Stu  fn()(当函数返回一个对象时,要创建一个临时对象以存放返回的对象)

{

Stu  ms;//在这里系统调用拷贝构造函数将ms拷贝到新创建的临时对象中

return ms;

}

Int main()

{

//Stu  s  =  fn();//浅拷贝

Stu  s;

s  =  fn();//深拷贝,拷贝的是资源的内容

}

创建的临时对象,在整个创建它们的外部表达式范围内有效,否则无效,也就是说,“s  =  fn();”这个外部表达式,当fn()返回时产生的临时对象拷贝给s后,临时对象就析构了。

(4)如果类需要析构函数来析构资源,则它也需要一个拷贝函数。

12

引用

C++尽量把引用作为形参

(1)类型&变量名

(2)定义之后必须马上初始化:int m;int  &b = m;m和b是等同的,b相当于常量指针一旦确定不能更改。

(3)一旦初始化之后不可更改,而指针是可以的

类中的所有的成员函数都可以访问类中全部的成员变量。

一个类的方法是自身类的有源,有源类的成员方法可以访问私有的变量。

构造函数可以调用成员函数。

引用与指针有什么区别?

1) 引用必须被初始化,指针不必。
2)
引用初始化以后不能被改变,指针可以改变所指的对象。
3)
不存在指向空值的引用,但是存在指向空值的指针。

 

13

继承(紧耦合)

子类:修饰符publicprivateprotected)父类名

定义:

class  Shape

{

private:

int  m_color;

proteceted:
       int  m_kind;      

public:

void printColor(){printf(“shape color %d\n”,m_color);}

Shape(){printf(“shape class constructed\n”);}

~Shape(){printf(“shape class destroy\n”);}

};

class Circle:public Shape

{

private:

float radius;

public:

Circle(){printf(“circle class constructed\n”);}

~Circle(){printf(“circle class destroy\n”);}

void printAera();

};

子类继承父类的时候:构造函数先完成父类的构造然后完成子类的构造,析构函数则是先完成子类的释放然后在完成父类的释放。如果是private继承的父类的public和protected域 将变成自己的private域。

private,protected:

单个类中:只能是类成员可以访问类的实例化的对象是不可以访问的

public:全部可以访问

一层继承(不论是何种继承,类成员可以直接访问 父类的protected,public)

(1)如果是public

派生类的实例化对象,访问父类的public但不能访问父类的protected

(2)如果是private或者是protected

派生类的实例化对象,不能访问父类的任何域

如果类中含有别的类对象:

本类::本类(参数列表):基类名(参数),对象1(参数),对象2(参数)……

{

本类的初始化工作;

}

14

多继承

virtual继承时需要在父类中添加无參的构造函数。

父类的指针可以指向子类,子类的指针不能指向父类。

15

虚函数的作用:允许在派生类中重新定义与基类同名的函数,并且可以通过基类指针或引用来访问基类和派生类中的同名函数。

任何一个类都有一个函数入口表,如果是虚的入口地址将会被更改

父类指针指向子类,从而使父类能够访问子类的成员。

虚函数一般不做成内联函数

 

纯虚函数:拥有纯虚函数的类是不能实例化的,称为抽象类(Java中的接口)。只要有一个纯虚函数就是抽象类,纯虚函数只能定义指针,指向派生类。

入口地址表不在内存中,增加虚函数(个数不限)内存大小增加一个指针大小4个字节。

16 this指针

《深入浅出MFC》中解释:

 定义类CRect,定义两个对象rect1、rect2,各有自己的m_color成员变量,但rect1.setcolor和rect2.setcolor却都是通往唯一的CRect::setcolor成员函数,那么CRect::setcolor如何处理不同对象的m_color?答案是由一个隐藏参数,名为this指针。当你调用:

rect1.setcolro(2);

rect2.setcolor(3);

时,编译器实际上为你做出来一下的代码:

CRect::setcolor(2,(CRect*)&rect1);

CRect::setcolor(3,(CRect*)&rect2);

多出来的参数,就是所谓的this指针。

17 指针

1、指针变量可以有空值,即指针变量不指向任何地址。

#include “iostream.h”

int  *p;  p=NULL;

int  *p;

p=0;

2、两指针可以相减,不可相加。若要进行相减运算,则两指针必须指向同一数组,相减结果为相距的数组元素个数

int   a[10],*p1,*p2;

p1=a;   p2=a+9;

p2-p1 :   9  

3、指向同一数组的两个指针变量可以比较大小:p2>p1

18

、有了 malloc/free 为什么还要 new/delete  ?

malloc 与 free 是 C++/C 语言的标准库函数,new/delete 是 C++的运算符。它们都可用于申请动态内存和释放内存。对于非内部数据类型的对象而言,光用 malloc/free 无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free 是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于 malloc/free。 因此 C++语言需要一个能完成动态内存分配和初始化工作的运算符 new,以及一个能完成清理与释放内存工作的运算符 delete。注意 new/delete 不是库函数。

 

19  字符串连接1

#include<stdio.h>

class CShape{

   private:

       int a;

   public:

    virtual void print(){ printf("CShape= %d\n",this->a);}

    virtual void hello() { printf("hello world\n");} 

 CShape(int x=3) { a=x;}

 

};

 

int main()

{

   CShape obj(10);

   typedef  void (*function)(CShape *thiss);

 

    char *ptr=(char *)&obj;

    int **p=(int **)ptr;

  

    function fpp=(function)(*(*p));

  

    function fpp1=(function)(*(*p+1));

    printf("*******virtaul function pointer**\n");

   (*fpp1)(&obj);

 

   (*fpp)(&obj);

   printf("*******object call function**\n");

   obj.hello();

   obj.print();

  

 

}

 

20 字符串连接2

#include <iostream>

using namespace std;

class String

{

       public:

              String()

              {

                     this->str=NULL;

              }

              String(char *s)

              {

                     str=(char *)malloc(sizeof(s));

                     memset(str,0,sizeof(s));

                     strcpy(str,s);

              }

              String operator+(const

                            String& s)

              {

                     String str3;

                     str3.str=(char *)malloc(sizeof(s.str)+sizeof(this->str));

                     memset(str3.str,0,sizeof(str3.str));

 

                     strcat(str3.str,this->str);

                     strcat(str3.str,s.str);

 

                     return str3;

              }

                void operator=(const String &s1)

              {

                     if(this->str!=NULL)

                            free(this->str);

                     this->str=(char *)malloc(sizeof(s1.str));

                     strcpy(this->str,s1.str);

                     //return *this;

              }

              friend String operator++(String &thiss)

              {

                     int i=0;

                     while(thiss.str[i]!='\0')

                     {

                            thiss.str[i]+=1;

                            i++;

                     }

              }

              void print()

              {

                     cout<<str<<endl;

              }

              ~String()

              {

                     if(str!=NULL)

                            free(str);

              }

       private:

              char *str;

};

int main()

{

       String s1("hello"),s2("world"),s3;

       s3 = s1+s2;

       s3.print();

       return 0;

}

 

posted on 2013-08-28 23:32  寻找心的巨人  阅读(194)  评论(0编辑  收藏  举报

导航