zoukankan      html  css  js  c++  java
  • c++:string//const//c与c++不同风格//多态//虚函数//强制转换...

    c++中字符串的处理,用string进行处理,实际上它是一个类.

    C++代码 复制代码 收藏代码
    1. string name;   
    2. name.size();   
    3. name.c_str();  
    string name;
    name.size();
    name.c_str();


    因此这里的name就是一个对象.
    name[下标],这样写不表示它是一个数组.

    char s[100] = "Hello";//应该是存在了栈空间里
    char* p = "Hello";//字符串存在常量区里,栈里只保存了一个地址
    输入输出时会对字符串进行特殊的处理.
    string不是C风格的字符串,是c++风格的,在c++里它会记录它的长度.
    在C里我们用strlen(地址),而在c++里我们用obj.size();
    在c++里我们用strlen(obj)是会出错的.
    ----------------------------------
    c++风格:

    C++代码 复制代码 收藏代码
    1. obj = "Hello";   
    2. obj[2] = '\0';   
    3. obj.size();  //返回5,注意这一点  
         obj = "Hello";
         obj[2] = '\0';
         obj.size();  //返回5,注意这一点


    可以直接输入输出,输入时不用考虑长度,自动会处理长度问题.

    C++代码 复制代码 收藏代码
    1. getline(cin,obj);   
    2. obj += 附加串  //不用考虑空间问题   
    3. obj1 >(<,==,>=,<=,!=) obj2 //直接比,结果为true,false   
    4. obj.c_str() ---> const char *  
    getline(cin,obj);
    obj += 附加串  //不用考虑空间问题
    obj1 >(<,==,>=,<=,!=) obj2 //直接比,结果为true,false
    obj.c_str() ---> const char *
    


    --------------------------------
    C风格字符串 :
    strcpy(地址,串)
    也可以直接输入输出,在输入时,必须要考虑数组长度的问题,避免越界
    cin.getline(地址,长度);
    strcat(旧串,附加串)   //注意长度
    strcmp(串1,串2)//结果正,负,0

    =================================================
    常量函数 在函数后加const
    无名对象:没有名字的对象,起到一个类型转换的作用.会的语句执行

    完后立即释放.
    单重继承:class Child:public Parent{};来自父类的私有成员不能

    在子类中直接访问.子类还可以扩展自已的东西,从而拥有比父类更丰富的内容

    .在创建时,会自动去调用父类的构造函数,如果要传参数,利用初始化列表传过

    去.一个函数的形参是可以有默认值的,在声明的时候就要指定默认值,而不是

    在定义时指定.初始化列表写在构造函数的函数头与函数体之间,因此必须在定

    义时才能有的,声明不能有.声明写默认值,主义时写初始化列表.
    覆盖:
    虚继承:是对菱形继承关系,virtual关键字的使用

    C++代码 复制代码 收藏代码
    1. //关于继承的例子程序,显示代分数   
    2. #include <iostream>   
    3. using namespace std;   
    4.   
    5. class Fract{   
    6.         int n;   
    7.         int d;   
    8. public:   
    9.         Fract():n(0),d(1){}   
    10.         Fract(int a, int b ):n(a),d(b){   
    11.                 reduce();   
    12.         }   
    13.         void reduce(){   
    14.                 if(d<0 ){d=-d;n=-n;}   
    15.                 if(d==0){cout << "ERROR" << endl;d=1;}   
    16.                 int absn = (n<0?-n:n);   
    17.                 for(int i=d;i>1;i--){   
    18.                         if(absn%i == 0 && d%i==0 ){   
    19.                                 n /= i;d/= i;   
    20.                                 break;   
    21.                         }   
    22.                 }   
    23.         }   
    24.         void show(){   
    25.                 cout << n << '/' << d << endl;   
    26.         }   
    27.         double value(){   
    28.                 return (double)n/d;   
    29.         }   
    30. };   
    31.   
    32. class Dai : public Fract{   
    33.         int i;   
    34. public :   
    35.         Dai():i(0){}   
    36.         Dai( int ai, int an, int ad ) : i(ai),Fract(an,ad){}   
    37.         void show(){   
    38.                 cout << i << '(' ;   
    39.                 Fract::show();   
    40.         cout << ')';   
    41.         }   
    42.         double value(){   
    43.                 return i+Fract::value();   
    44.         }   
    45. };   
    46. int main()   
    47. {   
    48.         Dai d1;   
    49.         Dai d2(2,12,16);   
    50.         d1.show();   
    51.         d2.show();   
    52. }  
    //关于继承的例子程序,显示代分数
    #include <iostream>
    using namespace std;
    
    class Fract{
            int n;
            int d;
    public:
            Fract():n(0),d(1){}
            Fract(int a, int b ):n(a),d(b){
                    reduce();
            }
            void reduce(){
                    if(d<0 ){d=-d;n=-n;}
                    if(d==0){cout << "ERROR" << endl;d=1;}
                    int absn = (n<0?-n:n);
                    for(int i=d;i>1;i--){
                            if(absn%i == 0 && d%i==0 ){
                                    n /= i;d/= i;
                                    break;
                            }
                    }
            }
            void show(){
                    cout << n << '/' << d << endl;
            }
            double value(){
                    return (double)n/d;
            }
    };
    
    class Dai : public Fract{
            int i;
    public :
            Dai():i(0){}
            Dai( int ai, int an, int ad ) : i(ai),Fract(an,ad){}
            void show(){
                    cout << i << '(' ;
                    Fract::show();
    		cout << ')';
            }
            double value(){
                    return i+Fract::value();
            }
    };
    int main()
    {
            Dai d1;
            Dai d2(2,12,16);
            d1.show();
            d2.show();
    }



    在Linux环境下用g++ fraction.cc进行编译连接,a.out运行可看到结果.

    =================================================
    * 多态 polymorphism

    父类对象 人类

    子类对像 司机类(小张)
    学生类(小王同学)

    子类对象总可以看成父类对象.
    多态的本质
    1,c++允许把派生类对象的地址赋给基类的指针
    3,用基类的指针调用任何方法,c++都能找到相应的派生类的方法.

    通过指针访问某个成员函数的时候,根据对象的真实类型执行子类中

    相应的函数
    多态的优势:统一管理,统一操作接口
    有virtual关键字的函数称为虚函数.在声明定义分开时,声明时写.
    多态的三个要素:
    1,继承关系
    2,调用的是虚函数
    3,访问到的是对象自已(用批针或引用),不能是另一个对象.

    C++代码 复制代码 收藏代码
    1. //例子   
    2. #include <iostream>   
    3. using namespace std;   
    4. #include <string>   
    5. class Animal{   
    6.     string name;   
    7. public:   
    8.     virtual void eat()=0;//一定不会被执行,纯虚函数   
    9.     virtual void sleep(){   
    10.         cout << "动物休息" << endl;   
    11.     }   
    12.     virtual void shout(){   
    13.         cout << "动物叫" << endl;   
    14.     }   
    15. };//注意分号   
    16. class Cat : public Animal{   
    17. public:   
    18.     virtual /* virtual 可写可不写 */ void eat(){   
    19.         cout << "猫写猫粮" << endl;   
    20.     }   
    21.     void sleep(){   
    22.         cout << "猫睡觉" << endl;   
    23.     }   
    24.     void shout(){   
    25.         cout << "猫喵喵叫" << endl;   
    26.     }      
    27. };//注意分号   
    28. class Dog : public Animal{   
    29. public :   
    30.     void eat(){   
    31.         cout << "狗吃骨头" << endl;   
    32.     }   
    33.     void sleep(){   
    34.         cout << "狗在睡觉" << endl;   
    35.     }   
    36.     void shout(){   
    37.         cout << "我叫旺财" << endl;   
    38.     }   
    39. };//分号不能少   
    40. class JiaFei : public Cat{   
    41. public :   
    42.     void eat(){   
    43.         cout << "加非猫爱吃意大利面" << endl;   
    44.     }   
    45.     void sleep(){   
    46.         cout << "加非猫睡在沙发上" << endl;   
    47.     }   
    48.     void shout(){   
    49.         cout << "加非猫说下午好" << endl;   
    50.     }   
    51. }; // 分号   
    52. class Player{   
    53.     string name;   
    54. public :   
    55.     Player( string n ) : name(n){}   
    56.     void play( Animal* p/*指针*/ ){   
    57.         p->eat();   
    58.         p->sleep();   
    59.         p->shout();     
    60.     }   
    61.     void play( Animal& p /*引用*/){   
    62.         p.eat();   
    63.         p.sleep();   
    64.         p.shout();     
    65.     }   
    66.   
    67. };  // 分号   
    68. int main()   
    69. {   
    70.     //cout << sizeof(Animal) << endl; //输出8   
    71.     Cat c;   
    72.     Dog d;   
    73.     JiaFei j;   
    74.     Player p1( "小小" );   
    75.     Player p2( "蔡依林");   
    76.     p1.play(&c);   
    77.     p2.play(&d);   
    78.     p2.play(&j);   
    79. }  
    //例子
    #include <iostream>
    using namespace std;
    #include <string>
    class Animal{
    	string name;
    public:
    	virtual void eat()=0;//一定不会被执行,纯虚函数
    	virtual void sleep(){
    		cout << "动物休息" << endl;
    	}
    	virtual void shout(){
    		cout << "动物叫" << endl;
    	}
    };//注意分号
    class Cat : public Animal{
    public:
    	virtual /* virtual 可写可不写 */ void eat(){
    		cout << "猫写猫粮" << endl;
    	}
    	void sleep(){
    		cout << "猫睡觉" << endl;
    	}
    	void shout(){
    		cout << "猫喵喵叫" << endl;
    	}	
    };//注意分号
    class Dog : public Animal{
    public :
    	void eat(){
    		cout << "狗吃骨头" << endl;
    	}
    	void sleep(){
    		cout << "狗在睡觉" << endl;
    	}
    	void shout(){
    		cout << "我叫旺财" << endl;
    	}
    };//分号不能少
    class JiaFei : public Cat{
    public :
    	void eat(){
    		cout << "加非猫爱吃意大利面" << endl;
    	}
    	void sleep(){
    		cout << "加非猫睡在沙发上" << endl;
    	}
    	void shout(){
    		cout << "加非猫说下午好" << endl;
    	}
    }; // 分号
    class Player{
    	string name;
    public :
    	Player( string n ) : name(n){}
    	void play( Animal* p/*指针*/ ){
    		p->eat();
    		p->sleep();
    		p->shout();	
    	}
    	void play( Animal& p /*引用*/){
    		p.eat();
    		p.sleep();
    		p.shout();	
    	}
    
    };	// 分号
    int main()
    {
    	//cout << sizeof(Animal) << endl; //输出8
    	Cat c;
    	Dog d;
    	JiaFei j;
    	Player p1( "小小" );
    	Player p2( "蔡依林");
    	p1.play(&c);
    	p2.play(&d);
    	p2.play(&j);
    }



    对有虚函数的类,编译器会申请一片空间,形成一个虚函数表,把所有

    的虚函数地址存在里面.所以多态是会有代价的.

    * 抽象类
    * 纯虚函数

    有纯虚函数的类叫做抽象类.对于抽象类没必要写函数体,因为如果写

    了会占用空间.
    纯虚函数一定不会被调用.所以抽象类不允许创建对象.
    只能用它来指向子类对象或是引用子类对象.
    这样就保证了一定不会执行纯虚函数.

    * 强制类型转换
    (类型) 数据 类型 (数据)
    不会改变源数据,根据类型产生新的数据,而++  --  = 可改变源数据.
    1,静态转换,static_cast  xxx_cast<类型>(数据)
    数值类型之间,有类型的指针与 void* 之间转换.
    无名类型支持的转换.
    static_cast<A>(100)  (A)100
    2,const_cast 把常量转换成变量.
    const X data;
    const_cast<X>(data)  //会重新产生一个变量
    const_cast<X&>(data)=1; //就是对当前常量进行处理
    volatile 不稳定的变量,基本不用
    auto 自动,默认的,无需人为的去加
    register 寄存器,
    register int n;//将n存在寄存器里,效率较高
    reinterpret_cast 重新解释内存,这也是最危险的转换,可以说是高手的游戏,

    一般人请不要用.因为什么都可以转.一般用在不同类型指针之间转换.
    reinterpret_cast<X*>(p) //这样用
    3,动态类型转换 dynamic_cast
    向上转换是安全的,向下转换就不一定了.
    dynamic_cast<子类*>(父类地址)  失败  NULL

    C++代码 复制代码 收藏代码
    1. //例子   
    2. #include <iostream>   
    3. using namespace std;   
    4.   
    5. class A{   
    6.         const int data;   
    7. public:   
    8.         A(){}   
    9.         A(int d) : data(d){}   
    10.         void show() const{   
    11.                 cout << "data=" << data << endl;   
    12.         }   
    13.         virtual void set(int d ){   
    14.                 const_cast<int &>(data) = d;   
    15.         } ///////////这样可以修改常量   
    16. };   
    17. class B : public A{   
    18. public :   
    19.         void sayhello(){   
    20.                 cout << "welcome" << endl;   
    21.         }   
    22. };   
    23. int main()   
    24. {   
    25.         static_cast<A>(188).show();   
    26.         A obj(200);   
    27.         obj.show();   
    28.         obj.set(259);   
    29.         obj.show();   
    30.         int i = 1;   
    31.         typedef unsigned char UC;   
    32.         UC *p = NULL;   
    33.         p = reinterpret_cast<UC*>(&i);   
    34.         for(int j=0; j<4; j++)   
    35.                 cout <<(int)*( p++) << ' ';   
    36.         cout << endl;   
    37.   
    38.         A oa;   
    39.         B ob;   
    40.         A* pa = &oa;   
    41.         B* pb = NULL;   
    42.         pb = dynamic_cast<B*>(pa);  //pb=(B*)pa;这样转是不安全的.   
    43.                      //dynamic_cast如果转换不了,会返   
    44.   
    45. 回一个NULL   
    46.         cout << "pb = " << pb << endl;   
    47.   
    48. }  
    //例子
    #include <iostream>
    using namespace std;
    
    class A{
            const int data;
    public:
            A(){}
            A(int d) : data(d){}
            void show() const{
                    cout << "data=" << data << endl;
            }
            virtual void set(int d ){
                    const_cast<int &>(data) = d;
            } ///////////这样可以修改常量
    };
    class B : public A{
    public :
            void sayhello(){
                    cout << "welcome" << endl;
            }
    };
    int main()
    {
            static_cast<A>(188).show();
            A obj(200);
            obj.show();
            obj.set(259);
            obj.show();
            int i = 1;
            typedef unsigned char UC;
            UC *p = NULL;
            p = reinterpret_cast<UC*>(&i);
            for(int j=0; j<4; j++)
                    cout <<(int)*( p++) << ' ';
            cout << endl;
    
            A oa;
            B ob;
            A* pa = &oa;
            B* pb = NULL;
            pb = dynamic_cast<B*>(pa);  //pb=(B*)pa;这样转是不安全的.
    				     //dynamic_cast如果转换不了,会返
    
    回一个NULL
            cout << "pb = " << pb << endl;
    
    }



    ----------------------------
    * 虚函数的使用
    构造函数不能是虚函数:因为我们是想用多态,根据我们的情况去调子

    类,而构造函数会首先调,不是主要调的,是自动调的,因此不能是虚函数
    如果类中有任何一个成员函数是虚函数,那么析构函数应为虚函数.因

    为我们想它会自动的去调相应的析构函数.
    如果一个类肯定被用作其他派生类的基类,尽可能使用虚函数.甚至可

    写成纯虚函数; 用=0;来代替函数体.

    C++代码 复制代码 收藏代码
    1. //例子程序   
    2. class A{   
    3. public :   
    4.     A(){cout << "'A()" << endl;}   
    5.     ~A(){cout << "'~A()" << endl;}   
    6. };   
    7. class B : public A {   
    8. public :   
    9.     B(){cout << "'B()" << endl;}   
    10.     ~B(){cout << "'~B()" << endl;}   
    11. };   
    12. int main()   
    13. {   
    14.     A* p = new B;   
    15.     delete p; // 此句会导致调用析构函数   
    16. }  
    //例子程序
    class A{
    public :
    	A(){cout << "'A()" << endl;}
    	~A(){cout << "'~A()" << endl;}
    };
    class B : public A {
    public :
    	B(){cout << "'B()" << endl;}
    	~B(){cout << "'~B()" << endl;}
    };
    int main()
    {
    	A* p = new B;
    	delete p; // 此句会导致调用析构函数
    }





    =================================================
    =================================================
    * 友员
    * 静态成员
    - 静态数据成员
    - 静态函数成员
    友员提供外面的函数或类直接访问某个类中私有成员的桥梁.
    友员也可理解为授权给某一个函数或类.
    在类的内部用 friend 声明;

    请注意啦 : 友员不是成员

    C++代码 复制代码 收藏代码
    1. //友员函数   
    2. #include <iostream>   
    3. using namespace std;   
    4.   
    5. class A {   
    6.         int data;   
    7. public :   
    8.         A( int d = 0 ) : data( d ) {}   
    9.         void show( ) {   
    10.                 cout << "data=" << data << endl;   
    11.         }   
    12.         friend A add(const A& a1,const  A& a2 );   
    13. };   
    14. A add ( const A& a1, const A& a2 ){  //这样写可形成习惯.   
    15.         int sum = a1.data +a2.data;   
    16.         return A(sum);   
    17. }   
    18. int main()   
    19. {   
    20.         A a1(20), a2(50);   
    21.         add(a1,a2).show();   
    22. }  
    //友员函数
    #include <iostream>
    using namespace std;
    
    class A {
            int data;
    public :
            A( int d = 0 ) : data( d ) {}
            void show( ) {
                    cout << "data=" << data << endl;
            }
            friend A add(const A& a1,const  A& a2 );
    };
    A add ( const A& a1, const A& a2 ){  //这样写可形成习惯.
            int sum = a1.data +a2.data;
            return A(sum);
    }
    int main()
    {
            A a1(20), a2(50);
            add(a1,a2).show();
    }



    C++代码 复制代码 收藏代码
    1. //友员类   
    2. #include <iostream>   
    3. using namespace std;   
    4.   
    5. class A {   
    6.         int data;   
    7. public :   
    8.         A( int d = 0 ) : data( d ) {}   
    9.         void show( ) {   
    10.                 cout << "data=" << data << endl;   
    11.         }   
    12.         friend A add(const A& a1,const  A& a2 );   
    13.         friend class B;   
    14. };   
    15. class B {   
    16. public :    
    17.         void twice(A& a){   
    18.                 a.data *= 2; //必须要通过 '对象名.成员' 来访问   
    19.         }   
    20. };   
    21.   
    22. A add ( const A& a1, const A& a2 ){   
    23.         int sum = a1.data + a2.data;   
    24.         return A(sum);   
    25. }   
    26.   
    27. int main()   
    28. {   
    29.         A oa(50);   
    30.         B ob;   
    31.         ob.twice(oa);   
    32.         oa.show();   
    33. }  
    //友员类
    #include <iostream>
    using namespace std;
    
    class A {
            int data;
    public :
            A( int d = 0 ) : data( d ) {}
            void show( ) {
                    cout << "data=" << data << endl;
            }
            friend A add(const A& a1,const  A& a2 );
            friend class B;
    };
    class B {
    public : 
            void twice(A& a){
                    a.data *= 2; //必须要通过 '对象名.成员' 来访问
            }
    };
    
    A add ( const A& a1, const A& a2 ){
            int sum = a1.data + a2.data;
            return A(sum);
    }
    
    int main()
    {
            A oa(50);
            B ob;
            ob.twice(oa);
            oa.show();
    }



    在实际开发中,凡是在函数中传递对象时,几乎都用引用,只要不改变

    此对象,也会加const

    * 静态数据成员

    凡是所有对象共用一份的数据都是要声明为静态数据成员.
    静态数据成员又称为类变量.
    静态的函数成员叫类方法.
    静态成员没必要创建一个对象初始化一次,一次性的初始化,不在构造函数中,

    而是在所有的函数之外.
    静态数据成员像全局变量一样,在所有函数之外初始化.

    C++代码 复制代码 收藏代码
    1. //例程   
    2. #include <iostream>   
    3. using namespace std;   
    4.   
    5. class Sd{   
    6. public :   
    7.     string name;   
    8.     static string teacher;   
    9.     static int room;   
    10.     Sd( const string& n) : name(n){   
    11.     }   
    12.     void show(){   
    13.         cout << "我是" << name << ",在" << room << "教室听"     
    14.   
    15. << teacher << "上课" << endl;   
    16.     }   
    17. };   
    18.   
    19. string Sd :: teacher = "小陈";// 静态成员要这样初始化   
    20. int Sd :: room = 213;   
    21. int main()   
    22. {   
    23.     Sd s1("伯乐");   
    24.     Sd s2("蔡依林");   
    25.     Sd s3("古天乐");   
    26.     s1.show();   
    27.     s2.show();   
    28.     s3.show();   
    29. }  
    //例程
    #include <iostream>
    using namespace std;
    
    class Sd{
    public :
    	string name;
    	static string teacher;
    	static int room;
    	Sd( const string& n) : name(n){
    	}
    	void show(){
    		cout << "我是" << name << ",在" << room << "教室听"  
    
    << teacher << "上课" << endl;
    	}
    };
    
    string Sd :: teacher = "小陈";// 静态成员要这样初始化
    int Sd :: room = 213;
    int main()
    {
    	Sd s1("伯乐");
    	Sd s2("蔡依林");
    	Sd s3("古天乐");
    	s1.show();
    	s2.show();
    	s3.show();
    }



    * 静态函数成员

    静态函数不能去访问非静态的数据成员.
    允许但不提倡用 对象.成员 来访问静态成员,类名::静态成员

    C++代码 复制代码 收藏代码
    1. #include <iostream>   
    2. using namespace std;   
    3.   
    4. class Sd{   
    5. public :   
    6.         string name;   
    7.         static string teacher;   
    8.         static int room;   
    9. #include <iostream>   
    10. using namespace std;   
    11.   
    12. class Sd{   
    13. public :   
    14.         string name;   
    15.         static string teacher;   
    16.         static int room;   
    17.         Sd( const string& n) : name(n){   
    18.         }   
    19.         void show(){   
    20. #include <iostream>   
    21. using namespace std;   
    22.   
    23. class Sd{   
    24. public :   
    25.         string name;   
    26.         static string teacher;   
    27.         static int room;   
    28.         Sd( const string& n) : name(n){   
    29.         }   
    30.         void show(){   
    31.                 cout << "我是" << name << ",在" << room << "教室听"  
    32.   
    33. << teacher << "上课" << endl;   
    34.         }   
    35.         static void newTeacher( const string& t){   
    36.                 teacher = t;   
    37.         }   
    38. };   
    39.   
    40. string Sd :: teacher = "小陈";// 静态成员要这样初始化   
    41. int Sd :: room = 213;   
    42. int main()   
    43. {   
    44.         Sd s1("伯乐");   
    45.         Sd s2("蔡依林");   
    46.         Sd s3("古天乐");   
    47.         s1.show();   
    48.         s2.show();   
    49.         s3.show();   
    50.         Sd::newTeacher("天使"); //通过类名访问静态函数   
    51.         s1.show();   
    52.         s2.show();   
    53.         s3.show();   
    54. }  
  • 相关阅读:
    linux 多进程并发服务__关于子进程回收的方法
    Qt中图元对象的多重集成
    Qmake: Q_OBJECT
    Qt Creator 启动失败 可能的解决办法
    Oracle 系统改变号SCN详解
    rman之创建恢复目录笔记
    Oracle 生成和显示执行计划的方法
    系统数据文件备份与恢复及只读数据文件备份与恢复
    没有备份、只有归档日志,如何恢复数据文件?
    ORACLE UNDO REDO查看
  • 原文地址:https://www.cnblogs.com/cuixiaodong427/p/2109266.html
Copyright © 2011-2022 走看看