\t\t谭浩强 C++ 学习笔记

来源:互联网 发布:汽车油漆调色软件下载 编辑:程序博客网 时间:2024/06/02 07:31

1 以const加以限定的引用的值不能改变,但是该引用对应的变量的值如果不是const则可以改变

 

2 可以用常量或表达式对引用进行初始化,但是必须加const加以限定

 

3 函数模板 

 template<typename T>  //这里没有“逗号”

 inline T Max(T a, T b)

 {

   //代码

 }

 

 所以应写成这样

#include "stdio.h"

#include <iostream>

using namespace std;

template <typename T> inline T Max(T a, T b)

if (a >= b)

{

return a;

}

else  

{

return b;

}

}

 

template <typename T > inline T Min(T a, T b)

{

if (a <= b)

{

return a;

}

else

{

return b;

}

}

 

 

int main()

int result = Max(10, 8);

cout<<result<<endl; 

cout<<Min(10 , 0)<<endl; 

return 0;

}

 

4 字符串常量以'\0'结束, 但是赋给字符串变量时 字符串变量不包括'\0'

 

5 在C++中,输出字符指针即输出字符(串)

//这里例子是验证字符指针的例子   

#include <iostream>

#include <string>

using namespace std;

int main(int argc, char *argv[])

{

 

cout<<argc<<endl; 

 

for (int i = 0; i<argc; i++)

{

cout<<argv[i]<<"**";//argv[i]为指针 在C++中 输出字符指针即输出字符串 如果输入*argv[i] 则输出

                    //的是每个参数的第一个字符

}

 

cout<<endl;

 

return 0;

}

 

6 C++中为了兼容C,也允许使用struct关键字定义类,只是把class换成struct即可,但是二者区别在于:如果不对成员函数和成员变量进行private protected public 

  修饰,class下默认为private, struct默认为public

  

7 为了减少因为调用函数而增加的时间开销,C++系统一般会将成员函数中不包括循环等控制结构的函数作为内联函数(inline)来处理,对类内定义的成员函数,一般

  省略inline关键字, 但对类外定义的成员函数则不会默认按inline函数来处理,如果需要要加inline关键字显示声明。

  在类外定义inline函数时类定义很函数定义必须写在一个文件里,但不利于类的接口与类的实现分离,从软件工程角度并不是一个好办法。

  PS:只有在类外定义的成员函数规模很小并且调用频率很高时才设置为inline函数,否则得不偿失。

  

8 在构造函数中对参数进行初始化时,如果形参和实参名相同:

①在用参数初始化表时不能用this指针 this.a(a)这种形式来初始化,可以直接写 a(a)

Volume::Volume(double length, double width, double height)

{

this->length = length;

this->width = width;

this->height = height;

}

 

②而不用这种方式时就必须用this.a = a;来初始化  如下

Volume::Volume(double length, double width, double height) :  length(length),  width(width),  height(height)

}

 

9 函数指针

  ①普通函数指针 

  函数返回值类型  (* 指针变量名) (参数列表);

  int (*p) (int a, char* b);

  ②类对象函数指针

  函数返回值类型 (类名::*指针变量名)(参数列表);

  指针变量名 = &类名::函数名;

  调用该函数时就可用*指针变量名代替

  int (Time::*p)();        //定义一个指向Time类公用成员函数的指针, 假如对应的函数不带参数

  p = &Time::GetTime;      //注意这里不带括号

  Time time;               //定义一个对象

  cout<<(time.*p)()<<endl; //输出时间    

  

  特别:指向常函数的指针

  char* (Boy::*pt)() const; //定义函数指针时要加const关键字,因为const也是函数的一部分

  pt = &Boy::GetName;       //pt指向const函数GetName()  

 

 

 10 const

   常对象只能调用const型的成员函数, const函数只能引用常对象中数据成员的值,若要修改则要在类声明时把数据成员声明为mutale int a;

   常数据成员在声明类时不能被赋值, 而且只能通过参数初始化列表进行初始化。

   const函数只能引用本类数据成员而不能修改其值。

   

 11 const成员函数只能引用数据成员而不管该数据成员是否是const型, 有一种例外就是在数据成员前加上 mutable 关键字表明是可以修改的。

    const对象只能调用const函数

不能用指向const对象的指针改变该const对象的值

 12 const类型变量定义时必须同时初始化

    const int a;

a = 3;           //错误

const int a = 3; //正确

常对象应该初始化,常指针也应该初始化

   

 13 指向const型变量的指针做函数形参时,传入的实参既可以是const类型也可以不是。

 

 

 14 static 静态数据成员,不能在构造函数中初始化,只能在类外初始化 

    int Box::height = 5;//类名Box  

 15 友元函数

    ①该函数为普通函数(非类的成员函数)

      在类中声明:    friend  返回值类型  函数名(类的引用);

      eg.  friend int Area(const Box &box); //如果该函数执行不需要改变实参的值,那么最好加上const修饰 类名Box

    ②该函数为其他类的成员函数

      如果该类A成员函数的参数中有一个参数为另一个类B对象或对象的引用,那么在在使用该类B的之前如果还没有声明该类,那么要用到类B的提前引用,即class B;

 

 一个函数(包括普通函数和成员函数)可以被多个类声明为“朋友”,friend写在谁那里,谁就被访问。

 eg.

 /********下面的代码包括以上两种情况*********************************************************/

#include <iostream>

using namespace std;

 

class Box

{

private: 

int length;

int height;

 

public:

Box(int length, int height) : length(length), height(height){}

friend int Area(const Box &box); //声明友元函数  该函数为一个普通函数 

friend void display(const Box &box); //声明  该函数为另一个类Time的成员函数  由于Box类声明在类Time之前,那么就不用类的提前引用。

};

 

 

 

int Area(const Box &box)

{

return box.length * box.height;

}

 

class Time

{

private:

int hour;

int minute;

int second;

 

public:

Time(int hour, int minute, int second) : hour(hour), minute(minute), second(second){}

void display(const Box &box);

};

 

void Time::display(const Box &box)

{

cout<<Area(box)<<endl;

cout<<hour<<":"<<minute<<":"<<second<<endl;

}

 

 

int main()

{

Box box(10, 20);

cout<<Area(box)<<endl;

Time time(17,01,26);

time.display(box);

 

return 0;

}

 

   /********上面的代码包括以上两种情况*********************************************************/

  

  16 类模板

     类名相当于: 类名 <template T>

     eg.  //以下这种情况是把函数定义写在类外,如果函数定义写在类体内则不必在函数前加 template <typename T> 和 类名 <T>

#include <iostream>

using namespace std;

 

template <typename T> // ⑤ 或 temelate <class T>

class Box

{

private:

T length;

T height;

static T width;

public:

Box(T length, T height) : length(length), height(height){}

void SetLength(T length);

T GetLength();

 

};

 

template <typename T>    //①

void Box <T> ::SetLength(T length)

{

this->length = length;

}

 

template <typename T>    //②

T Box <T> ::GetLength()

{

return this->length;

}

 

template <typename T>    //③

T Box <T> ::width = 5;

 

int main()

{

Box < int > box(1, 2); //④

cout<<box.GetLength()<<endl;

return 0;

}

17 指针数组空间释放

   遵循一个原则:有几个new就对应几个delete

eg.

class Student;

Student* st[] = {new Student(1,90), new Student(2,91), new Student(3, 98)}; //有三个new

for(int i = 0; i < 3; i++)

{

①delete st[i]; //释放指针指向的内存

st[i] = NULL; //避免出现野指针 使指针指空

}

或者②

delete[] *st; //把*st看成一个整体

st[i] = NULL;

18 运算符重载

  类型 operator 运算符  (参数);

  eg.

  class Complex; //复数类

  ①重载运算符函数作为类的成员函数时,双目运算符左侧必须是该类的对象,该重载函数的参数也必须至少有一个类对象或对象的引用。

  Complex operator+ (Complex &c);//声明

  

  Complex Complex::operator+ (Complex &c) //类外定义

  {

    Complex c;

c.real = this.real + c.real;

c.image = this.image + c.image;

return c;

  }

  

  int main()

  {

Complex c1(10.2, 5.6);

Complex c2(20.5, 4);

Complex c;

c = c1 + c2; //调用  c1.operator+(c2);   

return 0; 

  }

  

  ②作为友元函数

  friend Complex operator+ (Complex &c1, Complex &c2);//声明

  

  Complex operator+ (Complex &c1, Complex &c2)        //定义

  {

Complex c;

c.real = c1.real + c2.real;

c.image = c1.image + c2.image;

return c;   

  }

  

  int main()

  {

Complex c1(10.2, 5.6);

Complex c2(20.5, 4);

Complex c;

c = c1 + c2; //调用  operator+(c1,c2);   

return 0; 

  }

  

  ③也可以作为普通函数(略)

  

  PS: 当运算符重载函数作为友元函数时,在VC6下头文件要写成 #include<iostream.h>;  并去掉 using namespace std;

  

19 单目运算符重载 

  eg.   ++  --运算符的重载

   ①class Time;

Time operator++() //前置自增(自减)

{

if(++second == 60)

{

second = 0;

if(++minute == 60)

{

minute = 0;

}

}

return *this;//返回当前对象

}

  

   ② class Time;

Time operator++(int) //这里加一个int实参 则++为后自增(自减)

{

if(++second == 60)

{

second = 0;

if(++minute == 60)

{

minute = 0;

}

}

return *this;//返回当前对象

}

20 类的继承

  构造函数

  class Student;

  class Student1 : public Student

  {

public:

 Student1(char* name, int num);//构造函数声明 name是从父类Student继承而来, num是自己新加的成员 

 

private:

 int num;

  }

  

    //构造函数定义①

    Student1(char* name, int num) : Student(name)

{

this.num = num;

}

 

② 用参数初始化列表定义构造函数

     class Student1 : public Student

  {

public:

 Student1(char* name, int num) : Student(name), num(num){}  //参数初始化列表性形式

 

private:

 int num;

  }

  

  

    21 虚函数

  虚函数可实现多态,即一个基类的多层派生类中的同名同参函数,在不同情况下调用不同函数。

  定义指向基类的指针或引用, 该指针用或引用用子类地址赋值,然后用该指针调用该同名函数,即可实现调用不同函数体。

  eg.

  基类: class Point;

  子类: class Circle;

  二层子类: class Cylinder;

  Point *p = new Circle();

  cout<<p->Area(); //输出面积

  

  P = new Cylinder();

  cout<<p->Area(); //输出体积

  

22 纯虚函数

  virtual float Area() = 0;

  含有纯虚函数的类为抽象类,抽象类不能够实例化对象,该抽象类的子类如果不对纯虚函数进行定义则子类也为纯虚函数,即不能实例化对象。

 

 

原创粉丝点击