c++:string//const//c与c++不同风格//多态//虚函数//强制转换...

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

C++代码 复制代码  收藏代码spinner.gif
  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++代码 复制代码  收藏代码spinner.gif
  1. obj = "Hello";   
  2. obj[2] = '\0';   
  3. obj.size();  //返回5,注意这一点  
     obj = "Hello";
     obj[2] = '\0';
     obj.size();  //返回5,注意这一点


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

C++代码 复制代码  收藏代码spinner.gif
  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++代码 复制代码  收藏代码spinner.gif
  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++代码 复制代码  收藏代码spinner.gif
  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++代码 复制代码  收藏代码spinner.gif
  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++代码 复制代码  收藏代码spinner.gif
  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++代码 复制代码  收藏代码spinner.gif
  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++代码 复制代码  收藏代码spinner.gif
  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++代码 复制代码  收藏代码spinner.gif
  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++代码 复制代码  收藏代码spinner.gif
  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. }  

转载于:https://www.cnblogs.com/cuixiaodong427/archive/2011/07/18/2109266.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值