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

C++Primer笔记

2017-03-06 14:58 239 查看
C++Primer

 

术语、代码、执行的作用。

 

inline 内联函数

inline int abs( const tt &t )

避免函数调用的开销,即在被调用出展开

应该在头文件中定义

 

缺省实参

定义:char *screenInit( int height = 24, int width = 80,char background =' ' );

// 等价于 screenInit(24,80,' ')

调用:cursor = screenInit();

// 等价于 screenInit(66,88, ' ')

cursor = screenInit(66);

 

 

指向函数的指针

int gcd( int, int );

int (*pf)( int, int );

int main()

{

 pf=gcd;

   cout <<pf(2,3) << endl;

函数指针的数组

 pf=gcd;

 

extern

externint i;(extern 只声明不定义,去掉会造成重复定义)

externint i;(可以重复声明。)

 

extern int i ;(全局变量为0;extern可加可不加)

inti ;(error,重复定义)

intmain()

{

cout<<i << endl;

extern对于函数,同上。

局部对象

局部变量 自动对象

为初始化的内置类型局部变量,其初值不确定。

当函数调用结束时,自动对象就会撤销。

形参也是自动对象。

 一个变量如果位于函数的作用域内,但生命期跨越了这个函数的多次调用,这种变量往往很有用。应该将这样的对象对象定义为static。 static局部对象确保不迟于在程序执行流程第一次经过该对象的定义语句时进行初始化。这种对象一旦被创建,在程序结束前都不会撤销。

函数调用:调用前先保存寄存器,并在返回时恢复;

 

auto_ptr

释放数组

int *pia = new int[ 10 ];

delete[] str1;

 

constint *pci = new const int(1024);

deletepci;

 



全局域 局部域(方法内)

隐藏、::

intic=99;

  void abs2( int ic2)

{

cout<< ::ic+ic << endl;

名字空间

解决名字冲突问题

 

int i ;int i ;

 

声明、定义、调用:

namespacecplusplus_primer {

 class matrix { /* ... */ };

 void inverse ( matrix & );

constdouble pi = 3.1416;

 

 }

 void cplusplus_primer::inverse ( matrix &m){}

 void func( cplusplus_primer::matrix &m )

 {cplusplus_primer::inverse(m);}

 

    cplusplus_primer::matrix m;

     func(m );

 

名字空间的定义可以非连续

namespacecplusplus_primer {}

if( cur > ::max ) break;

嵌套域

cplusplus_primer::MatrixLib::matrix

隐藏 ::Type

隐藏 MatrixLib::val

 

未命名的名字空间

namespace {

 void swap2( double d1, double d2 ) { /* ... */}

 }

  swap2(3,4);

未命名名字空间成员名只在特定的文件中可见 在构成程序的其他文件中是不可

见的

// 短别名

 namespace mlib2 = cplusplus_primer::MatrixLib;

 namespace mlib=mlib2;

 // 较易读

 void func( mlib::matrix &m )

 {

cout << mlib::pi<< endl;

 }

    mlib::matrix m22;

  func( m22 );

 

usingcplusplus_primer::MatrixLib::matrix;

 matrix m22;

  func( m22 );

usingcplusplus_primer::MatrixLib::matrix; =using namespacecplusplus_primer::MatrixLib;

 

.

ostream& operator<< (ostream& o, const Screen& s ){

    cout << s.addToken()<< endl;

 }

int addToken( )const ;

 

 

类是一种抽象概念,其目的在于建立内存中的对象。其可以创建方法,来修改对象。

 

把成员函数声明为 const 以表明它们不修改类对象

只有被声明为 const 的成员函数才能被一个 const 类对象调用

把一个修改类数据成员的函数声明为 const 是非法的

构造函数和析构函数不是 const 成员函数 const类对象也可以调用它们

 

 

当构造函数执行结束 类对象已经被初始化时 类对象的常量性就

被建立起来了 析构函数一被调用 常量性就消失 所以一个 const 类对象 从构造完成时

刻到析构开始时刻 这段时间内被认为是 const

Account myAcct( "Tinkerbell");

Tinkerbell 被转换成一个临时的 string 对象(调用string构造函数),

调用Account构造函数

在初始化列表中初始化

在方法体中赋值。()

Tinkerbell 被转换成一个临时的 string 对象 然后该对象冉被传递给一个双参数的构

造函数 它的第一个参数是 string 类型

 

 

对于我们的新 string 类类型不够用 例如如下代码将失败

string new_client( "SteveHall" );

Account new_acct( new_client, 25000 );

因为在从 string 对象到 char*之间没有隐式转换 而写成

 

成员初始化表跟在构造函数的原型后 由冒号开头

如果成员是类对象 则初始值变成被传递给适当的构造函数的实参 该构造函数然后被应用在成员类对象上

在我们的例子中 name 被传递给

应用在_name 上的 string 构造函数 _balance 用参数 opening_bal 初始化

Account( const Account &rhs )

{

_name = rhs._name;

在隐式初始化阶段调用了缺省的 string 构造函数 并且在构造函数体内调用了

string 拷贝赋值操作符

成员初始化表:将成员的初始化和赋值分开。

 

缺省的按成员赋值 default memberwiseassignment 所处理的是 用一个类对象向该类

的另一个对象的赋值操作

利用了一个隐式的拷贝赋值操作符来取代拷贝构造函数

 

可能会生成一个缺省构造函数 但是它不会为内置或复

合型的数据成员 如指针或数组 提供初始值

拷贝构造函数 inline Account::Account( const Accout&rhs )

用一个类对象初始化该类的另一个对象被称为缺省按成员初始化

一个类对象向该类的另一个对象作拷贝是通过依次拷
4000
贝每个非静态数据成员来实现的


 

按成员赋值inline Account&Account::operator=(const Account &rhs )

一般来说 如果缺省的按成员初始化对于一个类不合适 则缺省的按成员赋值也不合适

 

Object-Oriented Programming

 

virtualostream& print( ostream& = cout ) const;

只有在通过基类指针或引用间接指向派生类子类型时 多态性才会起作用

 

// 错误: 关键字 virtual 只能出现在类定义中

virtual ostream& Query::print(ostream& ) const { ... }

 

 

int abs( const tt &t )

tt ttt(33);

const tt t2(ttt);

abs(ttt);

 

常量对象和引用不能被赋值,它们只能被初始化。 

估计初始化 在construction的list中,在函数被调用时形参。或在方法中,定义的时候。

然后就不能被赋值了。

不管是否有显式的初始化式,在执行构造函数之前,要初始化 isbn 成员。这个构造函数隐式使用默认的 string 构造函数来初始化 isbn。执行构造函数的函数体时,isbn 成员已经有值了。该值被构造函数函数体中的赋值所覆盖。

This constructor implicitly uses thedefault string constructor to initialize isbn. When the body of the constructoris executed, the isbn member already has a value. That value is overwritten bythe assignment inside the constructor body.

Sales_item::Sales_item(const string&book)

    {

         isbn = book;

         units_sold = 0;

         revenue = 0.0;

    }

 

Data members of class type are alwaysinitialized in the initialization phase, regardless of whether the member isinitialized explicitly in the constructor initializer list. Initializationhappens before the computation phase begins.

不管成员是否在构造函数初始化列表中显式初始化,类类型的数据成员总是在初始化阶段初始化。初始化发生在计算阶段开始之前。

 

    // no explicit constructor initializer: error ri is uninitialized

 

当用于类类型对象时,初始化的复制形式和直接形式有所不同:直接初始化直接调用与实参匹配的构造函数,复制初始化总是调用复制构造函数。复制初始化首先使用指定构造函数创建一个临时对象(第 7.3.2 节),然后用复制构造函数将那个临时对象复制到正在创建的对象:

    string null_book = "9-999-99999-9"; // copy-initialization

    string dots(10, '.');              // direct-initialization

 

    string empty_copy = string();      // copy-initialization

    string empty_direct;               // direct-initialization

 

For objects of class type,copy-initialization can be used only when specifying a single argument or whenwe explicitly build a temporary object to copy.

对于类类型对象,只有指定单个实参或显式创建一个临时对象用于复制时,才使用复制初始化。

When dots is created, the stringconstructor that takes a count and a character is called and directlyinitializes the members in dots. To create null_book, the compiler firstcreates a temporary by invoking the string constructor that takes a C-stylecharacter
string parameter. The compiler then uses the string copy constructorto initialize null_book as a copy of that temporary.


创建 dots 时,调用参数为一个数量和一个字符的 string 构造函数并直接初始化 dots 的成员。创建 null_book 时,编译器首先调用接受一个 C 风格字符串形参的 string 构造函数,创建一个临时对象,然后,编译器使用 string 复制构造函数将 null_book 初始化为那个临时对象的副本。

 

 

函数模板

 

template <class Type>

 Type min2( Type a, Type b );

 template <class Type>

 Type min2( Type a, Type b ) {

 return a < b ? a : b;

 }

pointer

template <class Parm, class U>

Parm minus2( Parm * array, U value )

{

Parm * p=array;

(*p)++;

}

int main()

{

int i =90;

minus2(&i,aa);

cout <<i<< endl;

 

template <typename Type, int size>

Type min( Type (&r_array)[size] )

{

Type min_val = r_array[2];

return min_val;

}

int main()

{

    int ia[] = { 10, 7,14, 3, 25 };

    cout<<min(ia)<< endl;

 

typename==class

 

 

int ia[]  !=  int *ia

 

学习数组,string int char


.

template <class Type>

// 第一个参数是 const Type*

void min3( const Type* array, int size ) {

// ...

}

int main()

{

        int ia[] = {10, 7, 14, 3, 25 };

    int *ia2 = ia;

// ok: 到 const int*
的限定修饰转换


    min3( ia2, 4 );

 

template <class T> T min5( T, T ) { /* ... */ }

unsigned int ui=77;

int main() {

// 错误:
不能实例化 min5( unsigned int, int )


// 必须是: min( unsigned int, unsigned int )


// min( int, int )

min5( ui, 1024 );

 

 

模板显式特化

 

// 通用的模板定义

template <class T>

T max3( T t1, T t2 ) {

return (t1 > t2 ? t1 : t2);

}

//typedef const char *PCC;

typedef int PCC;

template<> PCC max3< PCC >( PCC s1, PCC s2 ) {

return s1*2;

}

int main() {

      cout<<max3(44,333)<< endl;

 

 

template <class T1, class T2, class T3>

T1 sum3( T2 op1, T3 op2 ){

    return 33;

}

int main() {

    cout<<sum3(4.4,333)<< endl;

      cout<<sum3<int>(4.4,333)<< endl;

 

 

template <class T1, class T2, class T3>

T1 sum3( T2 op1, T3 op2 ){

    return 33;

}

template<> char sum3<char>( int, int ){

    return 'S';

}

int main() {

//    cout<<sum3(4.4,333)<< endl;

      cout<<sum3<char>(44,333)<< endl;

      cout<<sum3<int>(44,'3')<< endl;

      cout<<sum3<double>(4.4,33.3)<< endl;

 

函数模板可以被重载

 

 

类模板

 

 

 

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C++