复习C++一些基础知识

    xiaoxiao2021-03-25  311

    C++和C的不同之处

    1.变量的使用

    在C语言中局部变量必须在执行代码的前面,C++中变量的定义可以放到程序块的任何地方 eg for c++:

    for(int i = 0 ; i < 10 ; i++){}

    2.严格了函数的声明

    C语言中函数的声明很随意,C++中摒弃了这种随意的定义

    C: int add();//可以将参数直接省略 C++: int add(int a,int b);

    3.增加了重载机制

    重载是对一个名字或者符号多重意义的解释

    4.函数缺省参数

    C++中允许函数进行缺省 eg:

    声明: int f(int a, int b=2){ return a+b; } 调用下面两个结果相同: f(1,2); f(1);

    5.更加方便动态存储分配

    C++中提供动态分配的new和delete,增强C中的malloc(),free()

    6.增加内联函数

    C++中用内联函数取代C中的宏

    C: #define MAX(a,b) ((a)>(b)?(a):(b)) C++: inline int MAX(int a,int b) {   return a>b?a:b; }

    7.输入输出机制

    C++保留了C的标准输入输出,并且提供了一套新的输入输出机制

    C: printf("C"); C++: cout<<"C++"<<endl;

    8.增设了面向对象的思想和处理

    重点基础知识

    1.指针数组

    指针数组的元素类型是指针指针数组的元素存放对象的地址 类型 * 标识符 [ 表达式 ] ; int * pi [ 3 ] ;//其中int * 是每一个数组单元中存放的类型 float * pf [ 5 ] ;//其中float * 是每一个数组单元中存放的类型 char * ps [ 10 ] ;//其中char * 是每一个数组单元中存放的类型

    2.指向数组的指针数组

    double (*pf [3])[2] ; double a[2];

    对比这两个:

    double a[2]; a指向了一块具有两个元素的空间

    然后类比推理,(*pf [3])是一个数组,那么pf[0]的内容指向了一个具有两个空间的单元

    所以代码如下:

    #include<iostream.h> void main(){ double aa [2] = { 1.1, 2.2 } ; double bb [2] = { 3.3, 4.4 } ; double cc [2] = { 5.5, 6.6 } ; double ( * pf [3] ) [2] ; pf [0] = & aa ; pf [1] = & bb ; pf [2] = & cc ; for ( int i = 0 ; i < 3 ; i ++ ){ for ( int j = 0 ; j < 2 ; j ++ ) cout << * ( * pf [ i ] + j ) << " " ; cout << endl ; } }

    补充:

    一维数组类型的定义格式 typedef <元素类型关键字><数组类型名>[<常量表达式>];

    eg: typedef int vector[10];

    使用的时候:

    vector v1;相当于定义了一个有着10个int类型的数组。

    所以上面代码改成:

    #include<iostream.h> void main(){ typedef double aryType [2] ; aryType aa = { 1.1, 2.2 } ; aryType bb = { 3.3, 4.4 } ; aryType cc = { 5.5, 6.6 } ; aryType * pf [ 3 ] ; pf [0] = & aa ; pf [1] = & bb ; pf [2] = & cc ; for ( int i = 0 ; i < 3 ; i ++ ){ for ( int j = 0 ; j < 2 ; j ++ ) cout << * ( * pf [ i ] + j ) << " " ; cout << endl ; } }

    3.指向函数的指针数组

    // func.h #ifndef FUNC_H #define FUNC_H const float PI = 3.1415; float Square_Girth ( float l ) { return 4 * l ; } float Square_Area ( float l ) { return l * l ; } float Round_Girth ( float r ) { return 2 * PI * r ; } float Round_Area ( float r ) { return PI * r * r ; } typedef float ft ( float ) ; #endif //ex4_8.cpp #include<iostream.h> #include " func.h " void main() { int i ; float x = 1.23 ; ft * pfun [ 4 ] ; pfun [ 0 ] = Square_Girth ; pfun [ 1 ] = Square_Area ; pfun [ 2 ] = Round_Girth ; pfun [ 3 ] = Round_Area ; for ( i = 0 ; i < 4 ; i ++ ) cout << ( * pfun [ i ] ) ( x ) << endl ; return ; }

    其中typedef float ft ( float ) ;是定义函数

    4.new + delete

    int * p1 = new int ; int * p4 = new int [4] ; delete p1 ; delete [] p4 ;

    4.new建立动态数组

    int * p = NULL; p = new int [10] ; delete [] p ;

    特别的:

    #include<iostream.h> void App( int * & pa , int n ) ; void main(){ int *ary = NULL, *t , i, n ; cout<<"n= "; cin>>n; App( ary, n ); for( i = 0; i<n; i++ ) {ary[i] = 10 + i ; cout<<ary[i]<<" "; } delete []ary; } void App( int * & pa , int len ){ pa = new int [len] ; if( pa == NULL ){ cout << "allocation faiure\n"; return ; } for( int i = 0; i<len; i++ ) pa[i] = 0 ; }

    形参 int *pa是传地址值参数 调用函数时实参ary的值(NULL)赋给形参变量pa 函数App执行new操作把地址写入pa,与ary无关 函数返回后,ary不能获得动态数组的地址

    5.字符数组

    生成: char *string = "Student" ; 操作: strcpy ( string , "Student" ) ; char * name [ 5 ] = { "Li Hua" , "He Xiao Ming" , "Zhang Li" , "Sun Fei" , "Chen Biao" }

    C++中的核心基础


    声明: class AA { public: AA() { …… } ~AA() { …… } …… }; 调用: AA t1, t2 ;

    使用初始构造:

    使用“初始式”的构造函数形式为: 构造函数名 (变元表): 数据成员1 (变元表), … , 数据成员n (变元表) { /* …… */ }

    对象成员初始化

    #include<iostream.h> class A { public : A ( int x ) : a ( x ) { } int a ; } ; class B { public : B( int x, int y ) : aa( x ), b( y ) { } void out() { cout << "aa = " << aa.a << endl << "b = " << b << endl ; } private : int b ; A aa ; } ; void main (){ B objB( 3,5); objB . out ( ) ; }

    C++中运算符的重载

    可以重载的运算符 + - * / % ^ & | ~ ! = < > += -= *= /= % ^= &= |= << >> >>= <<= == != <= >= && || ++ -- ->* ‘ -> [] () new delete new[] delete[] 不能重载的算符 . :: .* ?: sizeof

    语法形式:

    类型 类名 :: operator op ( 参数表 ) { // 相对于该类定义的操作 }

    举个例子:

    这个例子中注意重载unsigned int operator() () ;其中运算符()

    #include<iostream.h> #include<stdlib.h> class Calculator { public: Calculator() { value = 0 ; } ; void operator ++ () ; void operator -- () ; unsigned int operator() () ; private: unsigned int value; }; void main() { Calculator Counter ; int i ; for( i = 0 ; i < 5 ; i ++ ) { ++ Counter; cout << "\n Counter = " << Counter() ; } for( i = 0 ; i <= 5 ; i ++ ) { -- Counter; cout << "\n Counter = " << Counter() ; } }

    实现:

    void Calculator::operator ++ () { if ( value < 65535 ) value ++ ; else { cout << "\nData overflow !" << endl ; abort() ; } } void Calculator::operator --() { if ( value > 0 ) value -- ; else { cout << "\n Data overflow !" << endl ; abort() ; } } unsigned int Calculator::operator() () { return value ; }

    重载下标运算符

    重载格式 类型 类 :: operator[] ( 类型 ) ; 例 设 x 是类 X 的一个对象,则表达式 x [ y ] 可被解释为 x . operator [ ] ( y )

    举个例子:

    #include<iostream.h> class vector { public : vector ( int n ) { v = new int [ n ] ; size = n ; } ~ vector ( ) { delete [ ] v ; size = 0 ; } int & operator [ ] ( int i ) { return v [ i ] ; } private : int * v ; int size ; }; void main ( ){ vector a ( 5 ) ; a [ 2 ] = 12 ; cout << a [ 2 ] << endl ; }

    多继承

    语法:

    class 派生类名 : 访问控制 基类名1 , 访问控制 基类名2 , … , 访问控制 基类名n { 数据成员和成员函数声明 };

    子类是在内存中拷贝了父类单元

    代码:

    class Base1 { public: Base1(int x) { value = x ; } int getData() const { return value ; } protected: int value; }; class Base2 { public: Base2(char c) { letter=c; } char getData() const { return letter;} protected: char letter; }; class Derived : public Base1, public Base2 { friend ostream &operator<< ( ostream &, const Derived & ) ; public : Derived ( int, char, double ) ; double getReal() const ; private : double real ; };

    虚基类

    通过代码:

    这段代码的结果是调用了两次A的构造函数

    #include < iostream.h > class A { public : A ( ) { cout << "class A" << endl ; } } ; class B : public A { public : B ( ) {cout << "class B" << endl ; } } ; class C : public A { public : C ( ) {cout << "class C" << endl ; } } ; class D : public B , public C { public : D ( ) {cout << "class D" << endl ; } } ; void main ( ) { D dd ; }

    看下面代码:

    只调用了一次A的构造函数

    #include < iostream.h > class A { public : A ( ) { cout << "class A" << endl ; } } ; class B : virtual public A { public : B ( ) {cout << "class B" << endl ; } } ; class C : virtual public A { public : C ( ) {cout << "class C" << endl ; } } ; class D : public B , public C { public : D ( ) {cout << "class D" << endl ; } } ; void main ( ) { D dd ; }

    虚函数与多态

    派生类指针引用基类对象

    派生类指针只有经过强制类型转换之后,才能引用基类对象 #include<iostream.h> #include<string.h> class Date { public: Date( int y, int m, int d ) { SetDate( y, m, d ); } void SetDate( int y, int m, int d ) { year = y ; month = m ; day = d ; } void Print() { cout << year << '/' << month << '/' << day << "; " ; } protected : int year , month , day ; } ; class DateTime : public Date { public : DateTime( int y, int m, int d, int h, int mi, int s ) : Date( y, m, d ) { SetTime( h, mi, s ); } void SetTime( int h, int mi, int s ) { hours = h; minutes = mi; seconds = s; } void Print() { ( ( Date * ) this ) -> Print();//对 this 指针作类型转换调用基类成员函数 cout << hours << ':' << minutes << ':' << seconds << '\n' ; } private: int hours , minutes , seconds ; }; void main() { DateTime dt( 2003, 1, 1, 12, 30, 0 ) ; dt.Print() ; }

    析构函数的调用

    当基类的指针指向派生类的对象,然后进行delete 基类指针的时候, 这个时候只是调用基类的析构函数,不会调用派生类的构造函数 #include<iostream.h> class A { public: ~A(){ cout << "A::~A() is called.\n" ; } } ; class B : public A { public: ~B(){ cout << "B::~B() is called.\n" ; } } ; void main() { A *Ap = new B ; B *Bp2 = new B ; cout << "delete first object:\n" ; delete Ap; cout << "delete second object:\n" ; delete Bp2 ; } 执行结果是: delete first object: A::~A() is called. delete second object: B::~B() is called. A::~A() is called.

    在析构函数前面加上virtual试试:

    #include<iostream.h> class A { public: ~A(){ cout << "A::~A() is called.\n" ; } } ; class B : public A { public: ~B(){ cout << "B::~B() is called.\n" ; } } ; void main() { A *Ap = new B ; B *Bp2 = new B ; cout << "delete first object:\n" ; delete Ap; cout << "delete second object:\n" ; delete Bp2 ; } 结果是: delete first object: B::~B() is called. A::~A() is called. delete second object: B::~B() is called. A::~A() is called.

    纯虚函数

    形式:

    virtual 类型 函数名(参数表)= 0 ;

    纯虚函数相当于Java中的接口,不能有实现,可以继承,继承如果实现的话,就可以产生对象,如果继承类没有实现则不能产生对象还是抽象类

    举个栗子:

    //Employee.h class Employee { public: Employee(const long,const char* ); virtual ~Employee(); const char * getName() const; const long getNumber() const; virtual double earnings() const=0; virtual void print() const; protected: long number; // 编号 char * name; // 姓名 };

    函数模板与模板函数 形式:

    template < 类型形式参数表 > 类型 函数名 ( 形式参数表 ) { 语句序列 }

    简单函数模板使用:

    #include <iostream.h> template < typename T > T max ( T a , T b ) { return a > b ? a : b ; } void main ( ) { cout << " max ( 3 , 5 ) is " << max ( 3 , 5 ) << endl ; cout << " max ( 'y' , 'e' ) is " << max ( 'y' , 'e' ) << endl ; cout << " max ( 9.3 , 0.5 ) is " << max ( 9.3 , 0.5 ) << endl ; }

    重载函数模板

    永远都是先精准匹配,然后不匹配在寻找模板

    template <typename T> T Max( const T a, const T b ) { return a>b ? a : b ; } template <typename T> T Max( const T a, const T b , const T c) { T t ; t = Max(a, b) ; return Max ( t, c ) ; } int Max( const int a , const char b ) { return a>b ? a : b ; }

    类模板

    形式:

    template <类型形式参数表> 类声明 template< typename Type > class TClass { // TClass的成员函数 private : Type DateMember ; //… };
    转载请注明原文地址: https://ju.6miu.com/read-171.html

    最新回复(0)