C++之面向对象(上)

发布时间:2016-12-8 12:19:04 编辑:www.fx114.net 分享查询网我要评论
本篇文章主要介绍了"C++之面向对象(上)",主要涉及到C++之面向对象(上)方面的内容,对于C++之面向对象(上)感兴趣的同学可以参考一下。

面向对象(上) 一,引用的应用 swap.cpp #include <iostream> using namespace std; int main(void){   int a = 10, b = 20;   swap1(a,b);   cout << "swap1:" << a << "," << b << endl;   swap2(&a, &b);   cout << "swap2:" << a << "," << b << endl;   swap3(&a, &b);   cout << "swap3:" << a << "," << b << endl;   return 0; } void swap1(int a, int b){    int c = a;    a = b;    b = c; }//传递的是实参a,b的复制,也就是副本 void swap2(int* a, int* b){    int c = *a;    *a = *b;    *b = c; }//传递的是实参a,b的地址 void swap3(int& a, int& b){    int c = a;    a = b;    b = c; }//引用的本质还是指针 实例二:交换字符串 int main(void){   const char* pa = "hello";   const char* pb = "world";   swap4 (pa,pb);   swap5(&pa,&pb);   cout << "swap4:" << pa << "," << pb << endl;   return 0; } void swap4(const char* pa, const char* pb){   const char* pc = pa;   pa = pb;   pb = pc; } //没有实现交换  两个参数指针是实参的副本 //可以将const char*替换为int进行看看 因为实参和形参都是指针。传递的是指针的值,还是值交换,所以没有改变 void swap5(const char** pa, const char** pb){    const char* pc = *pa;    *pa = *pb;    *pb = pc; }//这个是可以进行交换的 void swap6(const char*& pa, const char*& pb){   const char* pc = pa;   pa = pb;   pb = pc; }//这个也是可交换的 注:指针和引用从右向左看 当我们传递一个比较大的数值的时候,我们也可能会使用引用 这样用来提高效率 例如 int main(void){   return 0; } struct Student {   char name[128];   int age; } void print1(Student s){   cout << s.name << "," << s.age <<endl; }//值传递,复制,开销  void print2(Student& s){   cout << s.name << "," << s.age << endl; }//引用传递,不用复制,直接使用,效率高 void print3(const Student& s){   cout << s.name << "," << s.age << endl; }//引用传递效率高,但是有可能不需要在引用传递的时候 //改变值,所以为了避免这种情况,前面加一个const,常量 //不可修改 注:当返回值比较多的时候,那么怎么办呢? 我们可以使用引用,引用更改其中一个,在return返回另外一个 示例:计算圆的面积和周长 int main(void){   double area;   calcircle(3,area);   return 0; } void calcircle(double r, double& area){    area = 3.14 * r * r;    return 2 * 3.14 * r; } 注:area叫做输出参数  ,const类型的引用成为输入引用 故,通常情况下,const类型的引用用于输入,普通引用用于输出 二,类型转换 double f = 0.123; int n = (int)f; char* p = (char*)malloc(1024); 上面是明显的C风格的强制类型转换 1,静态类型转换:static_cast<类型>(变量); 需要编译器对类型转换安全性进行检查; 将void*转换为具体类型的指针 在源类型和目标类型之间只要有一个方向上可以做隐式类型转换, 那么在两个方向上就都可以做静态类型转换。 编译器所干的事儿是静态的 运行时所干的事儿是动态的 cast.cpp #include<iostream> #include<cstdlib> using namespace std; int main(void){   double f = 3.14;   int n = static_cast<int> (f);   cout << "n=" << n << endl;   char* p = static_cast<char*>(malloc(1024));   free(p);   return 0; } 结果是:3 2,动态类型转换:dynamic_cast<类型>(变量); 用在具有多态特性的父子类之间的转换 3,常量类型转换:const_cast<类型>(变量); 去除指针或者引用上的const属性。 const int cn = 100; int* pn = &cn; *pn = 200; const int cn = 100; int* pn = const_cast<int*>(&cn); *pn = 200; cout << *pn << "," << cn; 结果是:200,100 cn=100是从寄存器中读取的,而不是读取cn=200的内存中的 const volatile int cn = 100; int* pn = const_cast<int*>(&cn); *pn = 200; cout << *pn << "," << cn; 结果是:200,200 4,重解释类型转换:reinterpret_cast<类型>(变量); 允许对任意类型的指针进行转换 在指针和整形之间进行转换(32位的系统整形和指针都是4个字节) char * p = null; int n = reinterpret_cast<int>(p); double* pf = reinterpret_cast<double*>(p); 三,C++之父给C程序员的建议 1,尽量少用宏,而用const/enum、inline和模板 2,变量随用随声明 3,少用malloc 和 free,代之以new/delete 4,避免使用void*,指针算数,联合和强制类型转换 5,少用char*字符串,代之以string string.cpp #include<cstring> #include<iostream> using namespace std; int main(void){    char s1[] = "hello";    char s2[] = " world";    strcat(s1,s2);    cout << s1 << endl;    return 0; } c++中 string str ("hello"); str += " world"; cout << str << endl; string str2; str2 = str1; string类型可以直接赋值,而char数组类型的字符串需要使用 strcopy C++中字符串的比较可以使用大于小于等于 C中字符串的比较需要使用函数strcmp 6,OOP思想。过程/步骤-->对象/行为和属性 四,面向对象编程 1,什么是对象? 万物皆对象 属性和行为 程序就是一组对象,及其相互作用的描述 2,什么是类? 类是对对象的抽象。根据属性和行为的共性。 程序就是通过类的描述去表达对象及其相互关系 3,类和对象的关系 类是对象的抽象和描述,对象是类的具体化 4,访问控制修饰符 访问控制限定符   访控属性   自己  子类  其他 public            公有       ok    ok    ok protected         保护       ok    ok    no private           私有       ok    no    no 注:类的缺省访问控制属性是私有的。但是结构的缺省访问控制 属性是公有的。 student.cpp #include<iostream> using namespace std; class Student{    public:       void print(void){       cout << "我叫" << m_strName <<",今年"<< m_nAge <<"岁了" <<endl;    }    private:        string m_strName;        int m_nAge; } int main(void){    Student s;//定义了一个Student型的变量,实例化对象    s.print();    return 0; } 结果:我叫,今年768890岁了。 5,构造函数 class 类名{   类名(形参表){     构造函数体;   } }; #include<iostream> using namespace std; class Student{    public:       Student(string strName,int nAge){     m_strName = strName;          m_nAge = nAge;       }//带参构造函数       void print(void){       cout << "我叫" << m_strName <<",今年"<< m_nAge <<"岁了" <<endl;    }    private:        string m_strName;        int m_nAge; } int main(void){    Student s("张飞",28);//定义了一个Student型的变量,实例化对象    s.print();    return 0; } //上面的m_strName占用4字节,因为存储的是字符串的指针 6,对象的创建和销毁 1)在栈中创建对象 类名 对象名(构造参数); 如: Student s("张飞",28);//隐式构造 类名 对象名 = 类名(构造参数); 如: Student s = Student("张飞",28);//显式构造 2)在栈中创建对象数组 类名 数组名[元素个数] = {类名(构造参数),...}; 如: Student sa[3] = {Student("张飞",28),Student("赵云",29), Student("关羽",30)}; 注:元素个数可以缺省 3) 在堆中创建对象 类名* 对象指针 = new 类名(构造参数); 如: Student* ps = new Student("张飞",28); ps ->print(); delete ps; 4) 在堆中创建对象数组 构造函数可以重载 无参构造 Student(void){    m_strName = "lala";    m_nAge = 0; } 这时通过无参构造时候创建对象 Student s2();//错误,编译器会理解为函数声明 Student s2;//正确 堆中创建对象数组 类名* 对象数组指针 = new 类名[元素个数]; 如: Student* psa = new Student[3]; //上面的数组都是通过无参构造进行初始化的 只有在C++2011标准中才可以使用 Student* psa = new Student[3]{..有参构造或者无参构造...}; delete[] psa; 五,构造函数 1,默认的无参构造函数 如果一个类中没有定义任何构造函数,系统就会自动提供一个无参构造函数 如果为一个类定义了构造函数,系统就不会在为该类提供任何构造函数了。 2,构造函数可以重载 3,初始化列表 Student(string strName,int nAge):m_strName(strName),m_nAge(nAge){ } 1)需要对类类型的成员变量做初始化 class Date{ private:         int m_nYear; int m_nMonth; int m_nDay; Date(int nYear,int nMonth, int nDay):m_nYear(nYear),m_nMonth(nMonth),m_nDay(nDay){}   }   class Student{ private: string m_strName; int m_nAge; Date m_dtBirthDay; Student(string strName, int nAge,int nYear,int nMonth, int nDay):m_strName(strName),m_nAge(nAge),m_dtBirthDay(nYear,...){} Date dt;//编译错误,因为没有对应的构造函数 } 这种情况下需要使用初始化列表 非初始化列表,先创建再赋值 初始化列表,边创建边赋值 2)含有引用或常量类型成员 常量是必须在声明的同时进行初始化 引用页必须在声明的同时进行初始化 class Student{    public:       Student(string strName,int nAge):m_r(m_nAge){     m_strName = strName;          m_nAge = nAge;       }//带参构造函数       void print(void){       cout << "我叫" << m_strName <<",今年"<< m_nAge <<"岁了" <<endl;    }    private:        string m_strName;        int m_nAge;        int& m_r; } //报错:未初始化引用成员 #include<iostream> using namespace std; class A{ public: A (int n) : m_r(* new int(n)),m_c(100){} void show(void){   cout << m_r << "," << m_c << endl; }   private:   int& m_r;   const int m_c; }; int main(void){   A a(123);   a.show();   return 0; } 初始化的顺序不是取决于初始化列表,而是取决于成员变量的定义 初始化列表中的定义最好不要相互依赖 六,类的声明和定义可以相互分离 类的声明在.h文件 类的定义在.cpp文件中 s.h文件----------Student类的声明 #ifndef _S_H #define _S_H//防止重包含 #include <string> //C中的是#include<cstring> using namespace std; class Student{ public:  Student(const string& strName,int nAge);  void print(void); private:  string m_strName;  int m_nAge; } #endif //_S_H s.cpp---------------Student类的实现,注意Student::别忘记 #include "s.h" #include <iostream> Student::Student(const string& strName, int nAge):m_strName(strName),m_nAge(nAge){ } void Student::print(void){    cout << m_strName << "," << nAge << endl; } #include "s.h" int main(void){ Student s("张飞",28); s.print(); return 0; } %2d 设置字宽 setfill('0') setw(2);

上一篇:Android 颜色编码
下一篇:c/c++对齐规则

相关文章

相关评论