C++ Primer Plus学习笔记

来源:互联网 发布:王朔浮出海面 知乎 编辑:程序博客网 时间:2024/05/20 04:32

《C++ primer》第五版 第8-14章笔记

1. 宏替代

#include <iostream>using namespace std;#define SQUARE(X) ( (X) * (X) )int main(){int c = 3;// SQUARE(c++)将会被替代为( (c++) * (c++) ) cout << SQUARE(c++) << endl;  //将输出9而不是12,将整个表达式计算完之后才递增 cout << c << endl;  // 输出5 cin.get();return 0;} 


2. 临时对象为const类型

double cube( double & x ){return x * x * x; } int main(){double c = 3;cout << cube( c + 1.0 ) << endl; // 编译错误,c+1.0将产生一个临时对象,而临时// 对象在c++中都是const类型的,所以将cube的参数类型改为 const double & x即可 return 0;}

注:1> 实参的类型正确,但不是左值;2> 实参的类型不正确,但可以转换为正确的类型;

    这两种情况下,编译器会生成临时对象。P231(c++ perimer第五版)

 

3. extern定义的变量

//test.cpp#include <iostream>using namespace std;extern int num = 10; // 定义一个变量,外部链接,可以在其他文件中使用numvoid show(){<span style="white-space:pre"></span>cout << num << endl;<span style="white-space:pre"></span>cout << "hello world" << endl;<span style="white-space:pre"></span>return;} // test1.cpp#include <iostream>using namespace std;extern int num;extern void show();int main(){<span style="white-space:pre"></span>show();<span style="white-space:pre"></span>cout << num << endl;<span style="white-space:pre"></span>return 0;} 


4. const之前有无extern关键字的区别

例子1:// 1.cpp    num链接性为内部,即只能在1.cpp中使用,这就是为什么可以在头文件中定义const常量,//然后在其他文件包含该头文件而可以使用const常量const int num = 0;  void show(){cout << num << endl;return;}// 若要使得num为外部变量,即在其他文件中也可以使用,则只需添加extern关键字即可,如下:extern const int num = 20; // 其他文件中也可以使用num常量,外部链接,此处可以初始化(const数据必须初始化)// 具体见P278 《c++ primer第五版》 例子2:// test.cpp#include <iostream>using namespace std;int num = 10; // 定义一个变量,外部链接,可以在其他文件中使用numvoid show(){cout << "hello world" << endl;return;} // test1.cpp#include <iostream>using namespace std;// extern int num = 15; 错误,有extern并且初始化,相当于定义一个链接性为外部的变量,//即在其他文件中也可以使用此处定义的num常量,但是test.cpp中已经定义了num变量,//所以该处会出现重复定义的编译错误extern int num;  // 正确的声明,表面num在其他文件中已经定义了extern void show(); // 不需要extern也可以 具体见P278 《c++ primer第五版》int main(){show();cout << num << endl; // 输出10return 0;}

5. 创建的类对象是否能调用构造函数

// 5. h #include <iostream> class Stock{private:int m_num;public:void set();Stock();};// 6.cpp#include "5.h"using namespace std;void Stock::set() // 前面添加inline则表示内联函数{m_num = 2;std::cout << m_num << std::endl;return;} Stock::Stock(){cout << "constructro called" << endl; } // main.cpp#include <cstdlib>#include <iostream>#include "5.h" using namespace std; int main(int argc, char *argv[]){Stock test;test.set();  test.Stock();  // 编译错误-》构造函数被用来创建对象,而不能通过对象来调用,见P310(C++ Primer第五版)system("PAUSE");return EXIT_SUCCESS;}

6. P315 《C++ Primer第五版》

/////////////////////////////////////////////////// Filename:Stock.h/////////////////////////////////////////////////////#ifndef STOCK_H#define STOCK_H class Stock{private:char company[30];int shares;double share_val;double total_val;void set_tot(){total_val = shares * share_val;return;}public:Stock();Stock( const char *co, int n, double pr = 0.0 );Stock( const char *pch );~Stock();void show();};#endif /////////////////////////////////////////////////////// Filename:Stock.cpp////////////////////////////////////////////////////#include <iostream>#include "Stock.h" Stock::Stock(){std::cout << "Default constructor called!\n";std::strcpy( company, "no name" );shares = 0;share_val = 0.0;total_val = 0.0;} Stock::Stock( const char *co, int n, double pr ){std::cout << "Constructor using " << co << " called\n";std::strncpy( company, co, 29 );company[29] = '\0';if( n < 0 ){std::cerr << "Number of shares can not be negative; "<< company << " shares set to 0.\n";shares = 0; }else{shares = n;}share_val = pr;set_tot(); } Stock::Stock( const char *pch ){std::cout << pch << std::endl;strcpy( company, pch );} Stock::~Stock(){std::cout << "Bye, " << company << "!\n";} void Stock::show(){using std::cout;using std::endl;cout << "Company: " << company << " Shares: " << shares << endl<< " Share Price: $" << share_val << " Total Worth: $" << total_val << endl;return;} /////////////////////////////////////////////// Filename:main.cpp//////////////////////////////////////////// #include <iostream>#include "Stock.h" int main(){using namespace std;{Stock stock1( "stock1", 12, 20.0 );cout << "\nstock1 show:" << endl;stock1.show();cout << endl;Stock stock2 = Stock( "stock2", 2, 2.0 ); // Dev-C++编译运行不会产生临时对象 cout << "stock2 show:" << endl;stock2.show();stock2 = stock1;cout << "\nstock1 show:" << endl;stock1.show();cout << "\nstock2 show:" << endl;stock2.show();cout << endl;stock1 = Stock( "temp stock", 10, 50.0 );// Dev-C++编译运行会产生临时对象,并将临时对象赋值给stock1stock1.show();cout << "Done\n";Stock stock3 = "hello stock3"; //  Dev-C++编译运行不会调用Stock( const char *pch )产生临时对象,然后赋值为stock3,然后释放该临时对象,而是直接调用Stock( const char *pch )构造stock3对象}cin.get();return 0;}

运行结果:



 

7.   临时对象,拷贝构造函数,析构函数的调用

#include <iostream>class A{private:int num;public:A( int n ):num(n){std::cout << "constructor called " << num << std::endl;};A( const A &a ) // 拷贝构造函数{std::cout << "A( const A &a )'s &a " << &a << std::endl; std::cout << "copy constructor called " << std::endl;std::cout << "A( const A &a )'s this:" << this << std::endl;this->num = a.num; // 类成员函数可以访问私有变量 } ~A(){std::cout << "~A()'s this:" << this << std::endl;std::cout << "destructor called " << num << std::endl;}void print(){std::cout << num << std::endl;}}; A getA( A a ){std::cout << "getA()'s &a:"  << &a << std::endl; return a;}int main(){using namespace std;{A x(20); // 构造函数输出 cout << "main:&x: " << &x << endl;getA(x).print(); }cin.get();return 0;}  /*getA(x).print(); 执行流程:1. 调用类A的拷贝构造函数,传实参x传给拷贝构造函数,用来构造getA函数中的对象a ;2. getA函数返回时也会调用拷贝构造函数,传实参a给拷贝构造函数,用来在函数外部构造一个临时对象;3. 临时对象调用成员函数print();4. 临时对象调用析构函数并释放空间;5. getA函数中的局部对象a调用析构函数并释放空间;6. main函数中的对象x调用析构函数并释放空间.*/

/*

输出结果:

 

*/ 

 

8. 转换函数 P367《C++ Primer第五版》,赋值函数

#include <iostream> class A{private:int n;public:A( int nn):n(nn){std::cout << "constructor called: " << n << std::endl;}~A(){std::cout << "destructor called: " << n << std::endl;}A& operator=( const A &t ) // 赋值函数 {std::cout << "assign function called" << std::endl;A::n = t.n;// 用A::n也行 // this->n = t.n;} operator int()// 转换函数,将A对象转换为int类型 {return n;}}; int main(){using namespace std;{ A a = 2; // 会调用 A( int nn),不会先构造临时对象,而是直接调用A( int nn)构造对象a a = 3;  // 会先调用 A( int nn)构造临时对象,然后将临时对象赋值给a,完成后,临时对象释放 cout << a << endl; // 将调用转换函数,从而将A类型转换为int类型cout << (int)a << endl; // 也会调用转换函数}  cin.get();return 0;} /*输出结果:constructor called: 2constructor called: 3assign function calleddestructor called: 333destructor called: 3*/ 


9. 返回值对象,拷贝构造函数,编译器优化

#include <iostream> class A{private:int num;public:A( int n ):num(n){std::cout << "constructor called: " << n << std::endl;}~A(){std::cout << "destructor called: " << num << std::endl;}A( const A &a ){std::cout << "copy constructor called\n";this->num = a.num;}A& operator=( const A &a ) // 赋值操作符函数 {std::cout << "= function called\n";this->num = a.num;}friend std::ostream& operator<<( std::ostream &os, const A &a ){return os << a.num;}}; A getA( int num ){A a(num);std::cout << &a << std::endl;return a;} int main(){using namespace std;{A a1 = getA(1); // 不会调用拷贝构造函数,getA函数中直接在外部创建对象a1 // 而不会在getA函数中先创建对象a,然后调用拷贝构造函数构造a1,这里//编译器优化了,直接在外部创建对象a1了,并初始化为1,故getA函数结束时// 不会释放a了,因为此次调用没有在函数getA中创建局部变量a,而是直接在外部// 创建对象a1了 cout << &a1 << endl;cout << a1 << endl;A a2(4);  a2 = getA(2); // 这里是赋值,故在getA()中创建对象a,然后    // 调用赋值函数,赋值给a2,然后释放函数getA中的对象a cout << a2 << endl;}cin.get();return 0;} /*输出结果:constructor called: 10x22ff200x22ff201constructor called: 4constructor called: 20x22ff00= function calleddestructor called: 2  // 释放getA(2)调用中的对象a 2destructor called: 2  // 释放对象a2 destructor called: 1 // 释放对象a1 */ 

 

 

10. P484《C++ primer中文第五版》

#include <iostream>#include <string>#include <valarray>using namespace std; class Student{private:typedef valarray<double> ArrayDb;ArrayDb scores;string name;public:Student( int n ):name("Nully"), scores(n) // scores初始化为n个元素 {}double& operator[]( int i ) // 函数1 去掉&也能编译通过 {cout << "operator[](int i) called\n";return scores[i];}double operator[]( int i ) const //该函数与函数1是不同的函数,为函数重载 {cout << "operator[](int i) const called\n";return scores[i];}friend istream& operator>>( istream &is, Student &stu ){cout << "operator>> function called\n";is >> stu.name;return is;}};  int get(){int result = 9;return result;}  int main(){// cin >> get(); 编译不通过 ..................1 Student stu(1);cin >> stu;   // 调用operator>> cin >> stu[0];  // 调用double& operator[]( int i ),而不是double operator[]( int i )                // 若只有 double operator[]( int i ) 则会编译有错,类似上面的cin>>get()     cout << stu[0] << endl; // dev-C++中调用double& operator[]( int i ) system("pause");return 0;}//注:函数后面加const与不加const是不同的,可以因为这一区别而完成函数重载


 

 

 

 

0 0
原创粉丝点击