zoukankan      html  css  js  c++  java
  • C++的新手入门答疑

       1 基本部分:
       2 1、ctrl+f5 调试不运行,会出现press anykey to continue
       3 f5 调试
       4 2、c++变c,修改Stdafx.h,将#include<stdio.h>替换为#include<iostream>
       5 在主函数源文件中加入using namespace std;
       6 
       7 数据类型
       8 3、关于字符型变量。
       9 input:
      10 char a=10;
      11 int b=a+'a';
      12 output:b=17  13 但是字符型的输出不是整数,而是该整数所代表的ASCII码字符。
      14 input:
      15 char a=65;int b=65;
      16 cout<<a<<" "<<b<<endl;
      17 output:
      18 a 65
      19 4、关于常量,可用预处理命令,宏#define,也可用const定义。
      20 #define LIYAKUN 130
      21 const int liYaKun=130;
      22 
      23 基本结构:
      24 5、关于main函数
      25 存在int main(int argc,char *argv),arge表示有多少个参数被传递给主函数,argv[]表示参数以字符串数组的形式来传递。
      26 不存在void main(),main函数存在Int型的返回值。
      27 6、输入输出cin<<,cout>>.
      28 cin需要先按下enter键,然后才处理来自键盘的输入。
      29 
      30 运算符:
      31 7、C++中存在>=,<=,为关系运算符。
      32 
      33 数组:
      34 8、筛选法。可以通过较小的复杂度筛选出两组混杂的数据。
      35 
      36 函数:
      37 
      38 9、声明要放在头文件中,可以使被调函数与所有声明保持一致,如果函数接口发生变化,只需要修改唯一的声明。
      39 10、形参在函数调用结束后,形参分配的空间即被释放。
      40 11、值传递是无法实现其功能。
      41 void swap(int a,int b)
      42 {
      43 int temp;
      44 temp=a;
      45 a=b;
      46 b=temp;
      47 }
      48 12int _tmain(int argc, _TCHAR* argv[])可以兼容main()。
      49 13、内联函数inline可以减少函数调用时间,因为inline在编译时,在调用处直接用函数体进行替换。减少了普通函数在掉那样时的栈内存的创建和释放的开销。
      50 但是inline不能用循环、If语句,且必须要简洁。
      51 #include "stdafx.h"
      52 using namespace std;
      53 inline int swap(int a,int b);
      54 inline int swap(int a,int b)
      55 {
      56 int temp;
      57 temp=a;
      58 a=b;
      59 b=temp;
      60 return 0;
      61 }
      62 
      63 int _tmain(int argc, _TCHAR* argv[])
      64 {
      65 cout<<swap(1,2)<<endl; 
      66 return 0;
      67 }
      68 
      69 指针:
      70 14、指针运算符*,在定义的时候称为指针定义符,此时和指针运算符号的意义完全不同。它的作用是表示所声明的变量的数据类型是一个指针。
      71 int _tmain(int argc, _TCHAR* argv[])
      72 {
      73 int iValue=10;
      74 int *iPtr=&iValue;
      75 cout<<&iPtr<<endl;
      76 cout<<iPtr<<endl;
      77 cout<<*iPtr<<endl;
      78 }
      79 output:
      80 0071F938
      81 0071F938
      82 10
      83 15、指向函数的指针。实际上是指向存储函数代码的首地址。
      84 定义格式如:数据类型 (* 函数指针名)(形参表);
      85 注意:为了与返回指针的函数进行区别,第一个括号不能省略。
      86 在C++中,赋值的格式如:函数指针名(参数表);
      87 注意:函数指针变量不能进行算数运算,毫无意义。
      88 16、动态内存的分配方式。
      89 堆和栈:1)大小。栈是由系统自动分配的连续的地址空间,1M~2M。堆是通过链表来存储的空闲内存地址,受限于系统的虚拟内存,但远远大于栈的内存。2)栈主要是由局部变量,函参。堆是由程序员自行分配的内存区域。因此,栈的空间由系统自动释放,堆的空间由程序员释放。
      90 动态内存的分配:1)可用链表。也就是堆的方式。属于C++的方式。2)可用malloc等函数分配。是自由存储区的方式。属于C的方式。
      91 
      92 比较直观的感觉:当进行数组读写时,动态数组的下标可以用变量来表示。
      93 17、C++动态内存的分配。
      94 格式:new 类型名(初始值);如:pnValue=new int(3);//通过New分配了一个存放int类型的内存空间,并且将这个内存上写初始值3。
      95 注意:如果开辟动态内存,一定要判断是否开辟成功。
      96 如:int _tmain(int argc, _TCHAR* argv[])
      97 {
      98 int *pnValue;
      99 pnValue=new int(3);
     100 if (pnValue==NULL) exit(1);//如果内存开辟失败,指针为NULL
     101 else
     102 cout<<"Success!"<<endl;
     103 }
     104 18、C++动态内存的赋值。
     105 当申请空间为数组时,为其赋值不要用指针计算,如“pnValue++;”因为存储地址不是连续的,因此当退回时会出现错误。正确的方法是用过下标或者临时指针来访问动态数组。
     106 下标:int _tmain(int argc, _TCHAR* argv[])
     107 {
     108 int *pnArray=new int[5];
     109 pnArray[0]=1;
     110 pnArray[1]=2;
     111 }
     112 临时指针:int _tmain(int argc, _TCHAR* argv[])
     113 {
     114 int * pnArray=new int[5];
     115 int * pnArrayMove=pnArray;
     116 * pnArrayMove=1;
     117 pnArrayMove++;
     118 * pnArrayMove=2;
     119 }
     120 19、C++初始化动态数组。可用memset函数快速赋值
     121 格式:memset(指针名,初始化值,开辟空间的总字节数)
     122 如:int _tmain(int argc, _TCHAR* argv[])
     123 {
     124 long *plArray=new long[4];
     125 memset(plArray,0,sizeof(long)*5);//sizeof()不能计算动态内存容量
     126 }
     127 20、C++动态内存的释放。
     128 在C中我们用malloce申请,然后用free释放。在C++中我们用new来申请,用delete释放。同样,在释放以后,我们需要把这些指针赋值NULL。
     129 delete a;//a是动态内存变量
     130 delate[] a;//a是动态内存数组
     131 如:int _tmain(int argc, _TCHAR* argv[])
     132 {
     133 long *plArray=new long[10];//申请
     134 meset(plArray,0x00,sizeof(long)*10);//初始化
     135 
     136 delete[] plArray;//释放
     137 plArray=NULL;//赋值NULL
     138 }
     139 
     140 引用:
     141 21、引用时一个变量或者对象的别名。格式如下:数据类型& 所引用变量或对象名(目标变量或对象)。
     142 如:int _tmain(int argc, _TCHAR* argv[])
     143 {
     144 int nValue;
     145 int& rValue=nValue;
     146 return 0;
     147 }
     148 22、当引用作为函数参数出现时的情况。
     149 在函数被调用时,由于引用函数作为函数参数出现,因此系统在函数体中直接改变实参,这点跟指针的效果一样。这是引用出现的最常见的情况。
     150 如:void swap(int& a,int& b)
     151 {
     152 int temp;
     153 temp=a;
     154 a=b;
     155 b=temp;
     156 }
     157 
     158 int _tmain(int argc, _TCHAR* argv[])
     159 {
     160 int nValueA=10;
     161 int nValueB=20;
     162 int& rValueA=nValueA;
     163 int& rValueB=nValueB;
     164 cout<<nValueA<<","<<nValueB<<endl;
     165 swap(rValueA,rValueB);
     166 cout<<rValueA<<","<<rValueB<<endl;
     167 return 0;
     168 }
     169 输出:10,20
     170 20,10
     171 注意:此时,由于函数体改变了引用,。,nValueA=20,nValueB=10 172 !! 注意:引用的格式,必须为(类名& 实例名)!空格不能乱加。
     173 !!类名& 函数体(参数),含义是返回一个类的引用。类的实参返回。
     174 
     175 共用体:
     176 23、与结构体类型不同的是,共用体的提点1)同一共用体成员共用一个存储区,存储区大小等于最长字节的成员。2)同一时刻,在一个共用体变量中,只有一个成员起作用。
     177 
     178 字符串:
     179 24sizeof()是操作符,用来返回类型的大小,包括0,strlen()是函数,用来返回字符串的长度,其中不包括0 180 25、cin.getline(数组名称,读取字符数);这个函数读取一行,直至达到换行符,作为字符串的边界。
     181 
     182 类:
     183 26、类是C++封装的基本单位,它把数据和函数封装在一起。在定义一个类后,可以声明一个类的变量,即类的对象或者实例。
     184 class 类名 
     185 {
     186  187 };
     188 命名类的时候加前缀"C" 189 27、在定义类的时候,不为类分配存储空间,不能为类中的数据初始化。
     190 28、成员函数。在类中被声明:
     191 class 类名{
     192 访问控制关键字 返回值类型 成员函数名(参数表);
     193 };
     194 访问控制关键字:public/private(default)/protected,因为如果不对其进行设置,系统会默认设置,所以在定义时需要定义它的访问控制字。
     195 如下:
     196 class math(){
     197 public: //习惯性先设置公共部分
     198 void abs();
     199 void add();
     200 void mul();
     201 
     202 private:
     203 string number_1;
     204 string number_2;
     205 };
     206 29、成员函数在类外实现。
     207 class Cmath{
     208 void abs();
     209 }
     210 
     211 void Cmath::abs(){
     212 cout<<"Success!"<<endl;
     213 };
     214 30、类的实例,也称对象。当实例为非指针时,访问格式为“实例.类成员”;当实例为指针时,范根格式为“实例指针->类成员”。
     215 如:
     216 math HighMath;
     217 math *pHighMath;
     218 pHighMath=&HighMath;
     219 pHighMath->study();
     220 31、静态数据成员。
     221 当数据在类中声明为private控制型,但在程序过程中需要对它进行修改。此时可以加static来任何类的实例都可以对其数据进行改变。静态数据不属于任何一个实例,只能通过类名来访问。
     222 格式为:int CMath::jingtaishuju=0;
     223 不仅可以在main.cpp中访问,也可以在类实现文件中访问。
     224 32、静态成员函数。
     225 在1)没有实例生成时就需要访问类中的函数信息2)需要所有的类和对象都能访问时,用静态函数。
     226 定义格式:
     227 static 返回值类型 成员函数名(参数表)
     228 访问格式:
     229 类名::成员函数名
     230 
     231 构造函数
     232 33、构造函数。构造函数实现在实例被创建时利用特定的值去构造实例,将新建的实例初始化为一个特定状态。
     233 构造函数属于类里面的一个特殊的类,由系统自动调用,定义时无返回值。
     234 格式:
     235 类名();//构造函数名与类名相同
     236 34、带参数的构造函数。带参数的构造函数需要用实参来进行赋值。
     237 !!注意,带参数的构造函数和不带参数的构造函数可以同时存在,相当于构造函数的重载,可8以不带参数赋默认值,也可以带参数,先赋默认值,再赋参数。
     238 
     239 所以!最好在每次定义的时候都要写上不带参数的构造函数!
     240 
     241 这个地方容易产生很多错误,错例如下:
     242 Cmath xianxingdaishu;
     243 xianxingdaishu.Cmath(1,2,3);
     244 //错误!系统会在第一行语句中默认为,使用默认构造函数,因为构造函数是一直存在的。已经产生了实例以后,这样赋值就是不对的。
     245 如果构造函数要包含参数,就必须在定义的时候给出实参,实参甚至可以不用定义。
     246 改为:
     247 Cmath xianxingdaishu(1,2,3);//此处Cmath不是类名,而是构造函数名。
     248 格式:
     249 类名(初始化参数表);
     250 35、拷贝构造函数。
     251 用一个实例构造另一个实例,使其初始化为与原实例相同的数据,用拷贝构造函数。可以理解为,构造函数为类的一个特殊函数,拷贝构造函数为构造函数的一个特殊例子。拷贝构造函数与构造函数并存。
     252 声明格式:
     253 类名(类名& 实例名)//这里的实例名实际上就是参数名,形参
     254 实现格式:
     255 类名::拷贝构造函数名(类名& 实例参数)//实例参数:形参
     256 36、何时应该声明类头文件?
     257 只在类.cpp和主函数.cpp中声明 类.h。
     258 37、默认拷贝构造函数。
     259 如果不写拷贝构造函数,直接在定义的时候对其进行赋值初始化:
     260 如:
     261 //CMath.h
     262 class CMath{
     263 public:
     264 CMath(string strMathName,string trMathLength,float strMathLevel);//构造函数
     265 //CMath(CMath& MathModel);//拷贝构造函数
     266 void SetMathName();
     267 void SetMathLength();
     268 void SetMathLevel();
     269 void ShowMathName();
     270 void ShowMathLength();
     271 void ShowMathLevel();
     272 private:
     273 string m_strMathName;
     274 string m_strMathLength;
     275 float m_fMathLevel;
     276 };
     277 
     278 //CMath.cpp
     279 CMath::CMath(string MathName,string MathLength,float MathLevel){
     280 m_strMathName=MathName;
     281 m_strMathLength=MathLength;
     282 m_fMathLevel=MathLevel;
     283 };
     284 //主函数
     285 #include "stdafx.h"
     286 using namespace std;
     287 #include "CMath.h"
     288 #include "string.h"
     289 int _tmain(int argc, _TCHAR* argv[])
     290 {
     291 CMath MathModel1("FFT","fifty",8);
     292 CMath MathModel2=MathModel1;//调用了默认的拷贝构造函数
     293 MathModel2.ShowMathName();
     294 MathModel2.ShowMathLength();
     295 MathModel2.ShowMathLevel();
     296 }
     297 实际相当于,将所有的非静态变量都赋值给了新定义的实例。
     298 38、默认拷贝构造函数的局限。
     299 1)默认,是完全相同的赋值,实际上很多时候是不必要的。
     300 2)无法实现对动态内存进行拷贝。
     301 39、fatal error LNK1120: 1 个无法解析的外部命令。
     302 因为在头文件已经声明,但是在CPP文件中没有实现。
     303 40、深拷贝。由于存在默认拷贝构造函数的局限性,尤其是在对类中存在动态内存时无法拷贝,深拷贝能完成动态内存的拷贝。
     304 原理,在类中增加深拷贝函数,函数实现中先进行另外一个动态内存申请,然后再赋值。
     305 如:
     306 //CMath.h
     307 class CMath{
     308 public:
     309 CMath(string strMathName,string trMathLength,float strMathLevel);//构造函数
     310 CMath(CMath& MathModel);//拷贝构造函数,深拷贝
     311 void SetMathName();
     312 void SetMathLength();
     313 void SetMathLevel();
     314 void ShowMathName();
     315 void ShowMathLength();
     316 void ShowMathLevel();
     317 private:
     318 string * m_strMathName;//在实现函数中对其进行赋初值,new string
     319 string m_strMathLength;
     320 float m_fMathLevel;
     321 };
     322 //CMath.cpp
     323 CMath::CMath(string MathName,string MathLength,float MathLevel){
     324 m_strMathName=new string;//动态赋初值
     325 *m_strMathName=MathName;
     326 m_strMathLength=MathLength;
     327 m_fMathLevel=MathLevel;
     328 };
     329 CMath::CMath(CMath& MathModel){//建立拷贝构造函数
     330 m_strMathName=new string;//再开动态赋初值
     331 *m_strMathName=*MathModel.m_strMathName;
     332 m_strMathLength=MathModel.m_strMathLength;
     333 m_fMathLevel=MathModel.m_fMathLevel;
     334 };
     335 //主函数
     336 int _tmain(int argc, _TCHAR* argv[])
     337 {
     338 CMath MathModel1("FFT","fifty",8);
     339 CMath MathModel2(MathModel1);//引用已定义的实例
     340 MathModel2.ShowMathName();
     341 MathModel2.ShowMathLength();
     342 MathModel2.ShowMathLevel();
     343 }
     344 41、析构函数。对当前分配的资源进行清理。
     345 声明语法格式:~类名()//virtual ~CMath();//虚析构函数
     346 实现如:CMath::~CMath()
     347 {
     348 delete m_strMathName;
     349 m_strMathName=NULL;
     350 }
     351 注意:析构函数是默认存在的,程序员需要设置对其类中包含的动态变量进行析构。
     352 !!在主程序中不需要调用析构函数,因为系统会在实例的生存期结束以后自动调用类中的析构函数。
     353 !!一旦声明了析构函数,就必须对析构函数进行实现!
     354 42、类的组合。
     355 类的组合其实就是在类的声明里面嵌套其他的类。类的组合主要问题在于初始化,因为要同时对类的内嵌对象进行初始化。
     356 格式:类名::类名(形参表):内嵌对象1(形参表),内嵌对象2(形参表)
     357 {
     358 }
     359 //这个地方还有不清楚的地方。
     360 
     361 友元函数和友元类
     362 43、友元就是在需要访问多个类的私有参数时,用到了友元。但是在可以利用关键字friend来修饰。包括友元函数,友元类(类中所有函数都是友元函数)。
     363 声明格式:friend 返回值类型 函数名(参数);
     364 //EleSchStu.h
     365 class EleSchStu{
     366 public:
     367 void SetName(EleSchStu &);
     368 virtual ~EleSchStu();
     369 //设置友元函数来测试名字长度,不一定非要是引用型
     370 friend void CheckNameLength(EleSchStu &);
     371 private:
     372 string strName;
     373 static const int MAX_NAME_LEN;
     374 double score1;
     375 double score2;
     376 double score3;
     377 };
     378 //EleSchStu.cpp
     379 #include "stdafx.h"
     380 using namespace std;
     381 #include "EleSchStu.h"
     382 #include <string>
     383 
     384 void EleSchStu::SetName(EleSchStu &xiaoming){
     385 string str;
     386 cout<<"input the name:"<<endl;
     387 cin>>str;
     388 xiaoming.strName=str;
     389 };
     390 
     391 EleSchStu::~EleSchStu(){
     392 
     393 };
     394 void CheckNameLength(EleSchStu &xiaoming){
     395 if ((xiaoming.strName.length())>xiaoming.MAX_NAME_LEN)
     396 {
     397 cout<<"输入的名字长度太长了!"<<endl;
     398 }
     399 };
     400 //主函数
     401 const int EleSchStu::MAX_NAME_LEN=3;
     402 const int JuniorSchStu::MAX_NAME_LEN=3;
     403 int _tmain(int argc, _TCHAR* argv[])
     404 {
     405 EleSchStu xiaoming;
     406 xiaoming.SetName(xiaoming);
     407 CheckNameLength(xiaoming);
     408 return 0;
     409 }
     410 
     411 44、include <string>
     412 
     413 重载----重载函数和运算符重载
     414 45、重载函数。允许用同一个函数名定义多个函数,简化程序设计。从而使一个函数名就可以完成一系列相关的任务。
     415 重载函数如下一组: 
     416 long abs(long);
     417 double abs(double);
     418 注意!只有是返回类型、参数类型、参数个数、参数顺序上有所不同!不能仅仅是返回值不同。否则不能识别为重载函数。
     419 46、运算符重载。(operator)
     420 对已有的运算符赋予更多的含义。如:使同一个运算符作用于不同类型的数据。(运算符:+,-,*,/,%,new等)
     421 当运算符重载为成员函数时://关键字 operator
     422 格式:函数类型 operator 运算符 (形参表)
     423 {
     424 函数体;
     425 }
     426 为类的友元函数时:
     427 格式: friend 函数体 operator 运算符(形参表)
     428 {
     429 函数体:
     430 }
     431 47、转换运算符的重载。
     432 当用户自定义的数据类型也需要支持数据的转换时,需要用重载转换运算符。而且不能是友元函数。
     433 格式如下:
     434 operator 类型名();//返回类型其实就是类型名,所以不需要制定返回类型。
     435 48、赋值运算符的重载。
     436 关于重载的实例:
     437 需求:写出复数的+、-、*,用类的重载实现,分别用三个友元函数实现运算,能够显示原数据,最终分别用实例来验证三个算法。
     438 //CComplex.h
     439 #include <iostream>
     440 using namespace std;
     441 
     442 //CComplex.h
     443 class CComplex
     444 {
     445 public:
     446 CComplex();//不带参数的构造函数
     447 CComplex(double temp_real,double temp_imag);//含参的构造函数
     448 virtual ~CComplex();
     449 void show();
     450 private:
     451 double real;
     452 double imag;
     453 friend CComplex operator + (CComplex a,CComplex b);
     454 friend CComplex operator - (CComplex a,CComplex b);
     455 friend CComplex operator * (CComplex a,CComplex b);
     456 
     457 };
     458 //CComplex.cpp
     459 #include <iostream>
     460 using namespace std;
     461 #include "stdafx.h"
     462 #include "CComplex.h"
     463 
     464 CComplex::CComplex()
     465 {
     466 cout<<"默认构造函数……"<<endl;
     467 real=0;
     468 imag=0;
     469 }
     470 CComplex::CComplex(double temp_real,double temp_imag)
     471 {
     472 real=temp_real;
     473 imag=temp_imag;
     474 }
     475 CComplex::~CComplex()
     476 {
     477 }
     478 
     479 void CComplex::show()
     480 {
     481 cout<<"("<<real<<","<<imag<<")"<<endl;
     482 }
     483 
     484 CComplex operator + (CComplex a,CComplex b)
     485 {
     486 CComplex plus;
     487 plus.real=a.real+b.real;
     488 plus.imag=a.imag+b.imag;
     489 return plus;
     490 }
     491 
     492 CComplex operator - (CComplex a,CComplex b)
     493 {
     494 CComplex minus;
     495 minus.real=a.real-b.real;
     496 minus.imag=a.imag-b.imag;
     497 return minus;
     498 }
     499 
     500 CComplex operator * (CComplex a,CComplex b)
     501 {
     502 CComplex mult;
     503 mult.real=a.real*b.real-a.imag*b.imag;
     504 mult.imag=a.real*b.imag+a.imag*b.real;
     505 return mult;
     506 }
     507 //重载.cpp
     508 #include "stdafx.h"
     509 #include "CComplex.h"
     510 
     511 int _tmain(int argc, _TCHAR* argv[])
     512 {
     513 CComplex p1(1.0,2.0);
     514 CComplex p2(3.0,4.0);
     515 CComplex p3,p4,p5;
     516 p3=p1+p2;
     517 p4=p1-p2;
     518 p5=p1*p2;
     519 p1.show();
     520 p2.show();
     521 cout<<"+:";
     522 p3.show();
     523 cout<<"-:";
     524 p4.show();
     525 cout<<"*:";
     526 p5.show();
     527 return 0;
     528 }
     529 
     530 继承和派生:
     531 49、派生类。
     532 派生会接收基类中除了构造函数和析构函数以外的所有成员。也可以改造基类成员,对其进行覆盖和重载,也可以增加新的类成员。
     533 格式: 
     534 class 派生类名:继承方式 基类名1,继承方式 基类名2…
     535 //!继承只有一个冒号!
     536 {
     537 成员声明;
     538 }
     539 // 继承方式的关键字:public/protected/private(default)
     540 50、继承中的访问控制。
     541 
     542 为public继承时,基类中保护成员和公有成员在派生类中不变。
     543 为private继承时,基类中保护成员和公有成员在派生类中变为私有成员。(由于会中止类的继续派生,因此Private继承基本没用)
     544 为protected继承时,基类中保护成员和公有成员在派生类中变为保护成员。(在protected继承中,基类中的protected成员在基类的派生中的访问权限还是protected;在private继承中,基类中的protected成员在基类的派生中访问权限是private,因此在下一级的派生中,就无法访问基类的成员!!因此protected继承更加适合多层派生!!)
     545 
     546 !!所有的继承均无法访问基类中的私有成员。
     547 !!!Protected 与Public有区别!!protected是保护的,只有他自身或者继承他的类可以用,public是共有的,在静态下所有类都可以通过类名打点调用,不是静态下,可以用类对象点去调用。
     548 !!!???
     549 
     550 如例:
     551 #include "stdafx.h"
     552 //Point.h
     553 class CPoint
     554 {
     555 public:
     556 //CPoint();//构造函数
     557 virtual ~CPoint();
     558 void InitPoint(double x,double y);
     559 double GetX();
     560 double GetY();
     561 protected:
     562 double X,Y;
     563 };
     564 #endif
     565 //Linesegment.h
     566 #include "stdafx.h"
     567 #include "CPoint.h"
     568 class CLinesegment:protected CPoint
     569 {
     570 public:
     571 //CLinesegment();
     572 virtual ~CLinesegment();
     573 void InitLinesegment(double x,double y,double length);
     574 double GetX();//可以直接访问基类的保护成员
     575 double GetY();//可以直接访问基类的保护成员
     576 double GetLength();
     577 protected:
     578 //double X,Y;
     579 double Length;
     580 };
     581 //CPoint.cpp
     582 #include "stdafx.h"
     583 #include "CPoint.h"
     584 //#include "Linesegment.h"
     585 CPoint::~CPoint()
     586 {
     587 };
     588 void CPoint::InitPoint(double x,double y)
     589 {
     590 this->X=x;
     591 this->Y=y;
     592 };
     593 double CPoint::GetX()
     594 {
     595 return this->X;
     596 };
     597 double CPoint::GetY()
     598 {
     599 return this->Y;
     600 };
     601 //Linesegment.cpp
     602 #include "stdafx.h"
     603 #include "CPoint.h"
     604 #include "Linesegment.h"
     605 CLinesegment::~CLinesegment()
     606 {
     607 };
     608 void CLinesegment::InitLinesegment(double x,double y,double length)
     609 {
     610 InitPoint(x,y);//调用基类的函数
     611 this->Length=length;
     612 };
     613 double CLinesegment::GetX()//可以直接访问基类的保护成员?????,因为继承类中不存在x,y的成员变量
     614 {
     615 return this->X;
     616 };
     617 double CLinesegment::GetY()//可以直接访问基类的保护成员?????,因为继承类中不存在x,y的成员变量
     618 {
     619 return this->Y;
     620 };
     621 double CLinesegment::GetLength()
     622 {
     623 return this->Length;
     624 };
     625 //主函数
     626 // 保护继承.cpp : 定义控制台应用程序的入口点。
     627 #include "stdafx.h"
     628 #include "CPoint.h"
     629 #include "Linesegment.h"
     630 
     631 int _tmain(int argc, _TCHAR* argv[])
     632 {
     633 CLinesegment L1;
     634 L1.InitLinesegment(0,0,5);
     635 cout<<"("<<L1.GetX()<<","<<L1.GetY()<<","<<L1.GetLength()<<")"<<endl;
     636 return 0;
     637 }
     638 51、派生类的构造函数。
     639 由于派生类不能继承基类的构造函数,因此需要定义构造函数。
     640 声明格式: 构造函数(参数);
     641 实现格式:派生类名::派生类名(参数):继承方式1 基类名1(参数表1),继承方式2 基类名2(参数表2)...,内嵌实例名1(参数表1)//内嵌就是在派生类中又定义的类
     642 {
     643 派生类构造函数函数体;
     644 }
     645 !如果基类中没有自定义的构造函数,就将基类名(参数表)省略。所有都可以省略时,可以用生两侧派生类构造函数的成员初始化列表。
     646 52、派生类的析构函数。
     647 直接析构。
     648 53、派生类成员的标识和访问。
     649 格式:派生类实例名.基类名::成员名;
     650 派生类实例名.基类名::成员函数名(函数表);
     651 ::是作用域分辨符,可以用于限定要访问的成员所在的类的名称。
     652 !::不可以嵌套使用,比如:实例A.C1::C2::fun();错误!只能在C2函数中声明fun1(){},再调用fun()。
     653 54、虚基类:解决二义性的问题。
     654 声明格式:class 类名: virtual 继承方式 基类名。
     655 实例:定义一个车的基类,有最大速度、质量成员变量,及一些成员函数;派生出自行车类和汽车类,自行车有高度等成员变量,汽车有座位数等成员变量;从自行车和汽车派生出摩托车类。要求观察析构函数的执行和继承中,把车类设成虚基类和不设为虚基类的区别。
     656 //vehicle.h
     657 #ifndef _vehicle_h_
     658 #define _vehicle_h_
     659 #include "stdafx.h"
     660 class CVehicle
     661 {
     662 public:
     663 CVehicle();
     664 CVehicle(int speed,int weight);
     665 virtual ~CVehicle();
     666 protected:
     667 int Speed;
     668 int Weight;
     669 };
     670 #endif
     671 //vehicle.cpp
     672 #include "stdafx.h"
     673 #include "vehicle.h"
     674 
     675 CVehicle::CVehicle()
     676 {
     677 cout<<"CVehicle类的实例的构造函数生成!"<<endl;
     678 };
     679 CVehicle::CVehicle(int speed,int weight)
     680 {
     681 this->Speed=speed;
     682 this->Weight=weight;
     683 }
     684 CVehicle::~CVehicle()
     685 {
     686 cout<<"CVehicle类的实例的析构函数生成!"<<endl;
     687 };
     688 //bike.h
     689 #ifndef _bike_H_
     690 #define _bike_H_
     691 #include "stdafx.h"
     692 #include "vehicle.h"
     693 
     694 class CBike:virtual public CVehicle
     695 {
     696 public:
     697 CBike();
     698 CBike(int height);
     699 virtual ~CBike();
     700 protected:
     701 int height;
     702 };
     703 #endif
     704 //bike.cpp
     705 #include "stdafx.h"
     706 #include "vehicle.h"
     707 #include "bike.h"
     708 
     709 CBike::CBike()
     710 {
     711 cout<<"CBike类的实例的构造函数生成!"<<endl;
     712 };
     713 CBike::CBike(int height)
     714 {
     715 this->height=height;
     716 }
     717 CBike::~CBike()
     718 {
     719 cout<<"CBike类的实例的析构函数生成!"<<endl;
     720 };
     721 //car.h
     722 #ifndef _car_H_
     723 #define _car_H_
     724 
     725 #include "stdafx.h"
     726 #include "vehicle.h"
     727 
     728 class CCar:virtual protected CVehicle
     729 {
     730 public:
     731 CCar();
     732 CCar(int seat);
     733 virtual ~CCar();
     734 protected:
     735 int seat;
     736 };
     737 #endif
     738 //car.cpp
     739 #include "stdafx.h"
     740 #include "vehicle.h"
     741 #include "car.h"
     742 
     743 CCar::CCar()
     744 {
     745 cout<<"CCar类的实例的构造函数生成!"<<endl;
     746 };
     747 CCar::CCar(int seat)
     748 {
     749 this->seat=seat;
     750 };
     751 CCar::~CCar()
     752 {
     753 cout<<"CCar类的实例的析构函数生成!"<<endl;
     754 };
     755 //motor.h
     756 #ifndef _motor_H_
     757 #define _motor_H_
     758 
     759 #include "stdafx.h"
     760 #include "vehicle.h"
     761 #include "bike.h"
     762 #include "car.h"
     763 
     764 class CMotor: public CBike,public CCar
     765 {
     766 public:
     767 CMotor();
     768 CMotor(int speed, int weight, int height, int seat, int money):CVehicle(speed,weight),CCar(seat),CBike(height)
     769 {
     770 this->money=money;
     771 };
     772 virtual ~CMotor();
     773 void showMotor();
     774 protected:
     775 int money;
     776 };
     777 #endif
     778 //motor.cpp
     779 #include "stdafx.h"
     780 #include "vehicle.h"
     781 #include "car.h"
     782 #include "bike.h"
     783 #include "motor.h"
     784 
     785 CMotor::CMotor()
     786 {
     787 cout<<"构造CMotor类的实例!"<<endl;
     788 }
     789 CMotor::~CMotor()
     790 {
     791 cout<<"CMotor类的实例的析构函数生成!"<<endl;
     792 }
     793 void CMotor::showMotor()
     794 {
     795 void showCar();
     796 void showBike();
     797 //showVehicle();
     798 cout<<"speed="<<this->Speed<<endl;
     799 cout<<"weight="<<this->Weight<<endl;
     800 cout<<"height="<<this->height<<endl;
     801 cout<<"seat="<<this->seat<<endl;
     802 cout<<"money="<<this->money<<endl;
     803 }
     804 //主函数
     805 // 继承.cpp : 定义控制台应用程序的入口点。
     806 #include "stdafx.h"
     807 #include "vehicle.h"
     808 #include "car.h"
     809 #include "bike.h"
     810 #include "motor.h"
     811 
     812 int _tmain(int argc, _TCHAR* argv[])
     813 {
     814 int a=200,b=50000,c=1,d=4,e=100000;
     815 CMotor motor(a,b,c,d,e);
     816 motor.showMotor();
     817 return 0;
     818 }
     819 55、多态性
     820 指同一个函数,根据处理的对象不同,所调用的函数实现不同。通过虚函数来实现。
     821 56、虚函数。
     822 当基类定义的一个函数,派生类对函数进行了重载。重载以后,程序无法确定到底是哪个类调用了函数。
     823 当然,我们可以用作用域运算符来确定到底是哪个调用了。但有的情况下,程序会不知道:声明的函数到底调用了基类的对象,还是派生类的对象。因此,程序会默认调用了基类的对象,导致逻辑错误。
     824 !一句话概括:在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数。如果对象类型是派生类,就调用派生类的函数;如果对象类型是基类,就调用基类的函数。
     825 
     826 虚函数定义格式:
     827 virtual 函数返回格式 函数名()
     828 {
     829 };
     830 调用格式():
     831 Class CA
     832 {
     833 public:
     834  835 virtual float xuhanshu()
     836 {};
     837 }
     838 
     839 Class CB:public CA
     840 {
     841 public:
     842 ...
     843 virtual float xuhanshu()
     844 {};
     845 }
     846 //mian.cpp
     847 
     848 float get_xuhanshu(CA& temp)//注意参数类型
     849 {
     850 return temp.xuhanshu();
     851 }
     852 main()
     853 {
     854 CA test1;
     855 CB test2;
     856 get_xuhanshu(test1);//系统识别调用CA中的实例
     857 get_xuhanshu(test2);//系统识别调用CB中的实例
     858 }
     859 
     860 57、纯虚函数和抽象类。
     861 纯虚函数就是在一般的虚函数定义的后面加“=0”,本质上是将指向函数体的指针置零。
     862 抽象类是带有纯虚函数的类。抽象类的作用是为了建立类族的共同接口。抽象类不能实例化,但抽象类的派生类可以实例化。
     863 抽象类中的纯虚函数可以在主函数中实现,然后它的引用可以被任何派生类的实例调用。
     864 如:
     865 class A
     866 {
     867 ...
     868 virtual void display()=0;
     869 ...
     870 }
     871 class B:A
     872 {
     873 ...
     874 virtual void display()
     875 { cout<<"class B"<<endl;};
     876 ...
     877 }
     878 class C:B
     879 {
     880 ...
     881 virtual void display()
     882 { cout<<"class C"<<endl;};
     883 ...
     884 }
     885 //main.cpp
     886 void display(A& temp)
     887 {
     888 temp.display();
     889 }
     890 
     891 void main()
     892 {
     893 B b;
     894 C c;
     895 display(b);//相当于在主函数中声明了一个函数,只要是A类族的参数都可以调用。
     896 display(c);
     897 }
     898 output: 
     899 class B
     900 class C
     901 
     902 例子:抽象类shape,5个派生类,circle,square,rectangle,trapezoid,triangle,用虚函数分别计算几个图形面积,并求它们的和。用基类指针数组,使它的每一个元素指向一个派生类对象。
     903 //shape.h
     904 #ifndef _Shape_H_
     905 #define _Shape_H_
     906 #include "stdafx.h"
     907 class Shape
     908 {
     909 public:
     910 virtual void show(){};
     911 virtual double area()=0;//只有含返回参数的成员函数,才能当作纯虚函数
     912 //主要当作一个接口
     913 };
     914 #endif
     915 //circle.h
     916 #include "stdafx.h"
     917 #include "shape.h"
     918 #include <math.h>
     919 
     920 class circle:public Shape
     921 {
     922 public:
     923 circle(double temp_r)
     924 {
     925 r=temp_r;
     926 };
     927 virtual ~circle(){};
     928 void show()
     929 {
     930 double temp;
     931 temp=area();
     932 cout<<"this is circle! the area is "<<temp<<endl;
     933 };
     934 double area()
     935 {
     936 double temp;
     937 temp=r*r*3.14;
     938 return temp;
     939 };
     940 protected:
     941 double r;
     942 };
     943 //square.h
     944 #include "stdafx.h"
     945 #include "shape.h"
     946 #include <math.h>
     947 class square:public Shape
     948 {
     949 public:
     950 square(double l)
     951 {
     952 this->l=l;
     953 };
     954 virtual ~square(){};
     955 double area()
     956 {
     957 double temp;
     958 temp=this->l*this->l;
     959 return temp;
     960 }
     961 void show()
     962 {
     963 double temp=this->area();
     964 cout<<"this is square!,the area is "<<temp<<endl;
     965 }
     966 protected:
     967 double l;
     968 };
     969 
     970 //main.cpp
     971 // 虚函数.cpp : 定义控制台应用程序的入口点。
     972 #include "stdafx.h"
     973 #include "shape.h"
     974 #include "circle.h"
     975 #include "square.h"
     976 #include <math.h>
     977 
     978 int _tmain(int argc, _TCHAR* argv[])
     979 {
     980 circle c(5);
     981 square s(5);
     982 Shape *p[2];
     983 p[0]=&c;//虚基类的实例可以指向派生类的引用
     984 p[1]=&s;
     985 p[0]->show();
     986 p[1]->show();
     987 return 0;
     988 }
     989 输入输出体系:
     990 58、流。
     991 流其实形象的比喻了C++中数据传输的过程。
     992 流操作包含了许多类。类名包括:ios,istream,ostream...
     993 59、流格式化输出。
     994 如果需要控制流输出的格式,如果要控制流输出的格式。一种用流格式控制符;另一种是利用流类的相关成员函数进行控制。
     995 1)流控制符:
     996 需要定义头文件<iomanip>;
     997 应用如:
     998 int a=15;
     999 cout<<"十进制"<<dec<<a<<endl;//以十进制形式输出整数a
    1000 cout<<"十六进制"<<hex<<a<<endl; 
    1001 double pi=3.14;
    1002 cout<<"指数形式"<<setiosflags(ios::scientific)<<setprecision(8);
    1003 //不需要记住,只需要知道按指数形式输出,8位小数
    1004 2)流控制成员函数。具体应用要具体查文档。
    1005 60、文件操作。
    1006 首先需要定义输入输出文件流对象头文件<fstream>1007 声明对象:
    1008 ifstream file_in;//建立输入文件流对象
    1009 ofstream file_out;//建立输出文件流对象
    1010 fstream file_inout;//建立输入输出文件流对象
    1011 构造函数:
    1012 ifstream::ifstream(const char*,int=ios::in,int=filebuf::openprot);
    1013 ofstream::ofstream(congst char*,int=ios::out,int=filebuf::openprot);
    1014 fstream::fstream(cont char*,int,int=filebuf::operprot);
    1015 调用构造函数如:
    1016 ofstream file_out("C:\a_out.dat",ios::out|ios::binary);//以二进制方式打开输出文件。
    1017 61、检查是是否打开文件。关闭文件。
    1018 bool fail();//失败返回true,成功返回false。
    1019 类中的成员函数close():
    1020 void close();
    1021 62、关于写文件。
    1022 分为读写字符型文件(主要是读写到.txt)和二进制文件(都写到.dat)。
    1023 具体应用如下。
    1024 // 打开文件.cpp : 定义控制台应用程序的入口点。
    1025 #include "stdafx.h"
    1026 #include <iostream>
    1027 #include <fstream>
    1028 using namespace std;
    1029 
    1030 int _tmain(int argc, _TCHAR* argv[])
    1031 {
    1032 //打开文件!
    1033 ofstream file_out;//定义打开文件类
    1034 
    1035 file_out.open("C:\c++.txt",ios::out|ios::app);//打开文件,用于数据输出,从文件中写数据,app是以数据追加方式打开。
    1036 if(file_out.fail())     //如果文件打开失败,则显示出错信息。
    1037 {
    1038 cerr<<"文件 c++.txt 打开失败!"<<endl;
    1039 return 1;
    1040 }
    1041 
    1042 //输出到文件!
    1043 //利用插入操作符进行输出
    1044 file_out<<"wo cao ni ma!"<<endl;
    1045 file_out<<"我草泥马!"<<endl;
    1046 
    1047 //利用put()进行输出
    1048 char a = '!';
    1049 file_out.put(a);
    1050 
    1051 //文件的内容输入到内存!
    1052 //利用提取操作符
    1053 ifstream file_in;//定义打开文件类
    1054 
    1055 file_in.open("C:\c++.txt",ios::in);//打开文件,用于数据输入,从文件中读数据)
    1056 if(file_in.fail())     //如果文件打开失败,则显示出错信息。
    1057 {
    1058 cerr<<"文件 c++.txt 打开失败!"<<endl;
    1059 return 1;
    1060 }
    1061 
    1062 char nRead = 0;
    1063 while (!file_in>>nRead)//读取字符,注意,提取的时候是忽略换行和空格字符的
    1064 {
    1065 cout<<nRead<<" ";//" "即为输出字符
    1066 }
    1067 
    1068 
    1069 while (!file_in.eof())//读取字符,注意,提取的时候是包括换行和空格字符的
    1070 //eof()用于判断指针是否已经到文件的末尾了,当返回ture时,已经到达文件的尾部
    1071 {
    1072 file_in.get(nRead);
    1073 cout<<nRead;
    1074 }
    1075 
    1076 file_out.close();//关闭文件
    1077 file_in.close();
    1078 
    1079 return 0;
    1080 }
    1081 实例:定义一个结构体,通过键盘输入学生的信息并保存到磁盘stud.dat文件中,并从中读出来显示在屏幕上。
    1082 // 二进制文件操作.cpp : 定义控制台应用程序的入口点。
    1083 #include "stdafx.h"
    1084 #include <iostream>
    1085 using namespace std;
    1086 #include <string>
    1087 #include <fstream>
    1088 
    1089 struct Student
    1090 {
    1091 char name[20];
    1092 int age;
    1093 char No[20];
    1094 char sex[20];
    1095 };
    1096 int _tmain(int argc, _TCHAR* argv[])
    1097 {
    1098 Student stu[2];
    1099 int i;
    1100 int j=0;
    1101 for(i=0;i<2;i++)
    1102 {
    1103 cout<<"please insert your name:";
    1104 cin>>stu[i].name;
    1105 cout<<"please insert your age:";
    1106 cin>>stu[i].age;
    1107 cout<<"please insert your Number:";
    1108 cin>>stu[i].No;
    1109 cout<<"please insert your sex:";
    1110 cin>>stu[i].sex;
    1111 }
    1112 ofstream put_in("C:\c++.dat",ios::out|ios::binary);//打开二进制文件
    1113 if (!put_in)     //判断是否打开成功
    1114 {
    1115 cerr<<"C:\c++.dat can't open it..."<<endl;
    1116 exit(1);
    1117 }
    1118 for(i=0;i<2;i++)
    1119 {
    1120 put_in.write((char *) &stu[i],sizeof(stu[i]));//文件写入的时候用的是指针,而不是内容
    1121 }
    1122 put_in.close();
    1123 
    1124 ifstream put_out("C:\c++.dat",ios::out|ios::binary);//打开二进制文件
    1125 if (!put_out)
    1126 {
    1127 cerr<<"C:\c++.dat can't open it..."<<endl;
    1128 exit(1);
    1129 }
    1130 for(i=0;i<2;i++)
    1131 {
    1132 put_out.read((char *) &stu[i],sizeof(stu[i]));//成语按函数read()来读二进制文件
    1133 }
    1134 put_out.close();
    1135 for(i=0;i<2;i++)     //输出!
    1136 {
    1137 cout<<"the "<<i+1<<" name:";
    1138 cout<<stu[i].name<<endl;
    1139 cout<<"the "<<i+1<<" age:";
    1140 cout<<stu[i].age<<endl;
    1141 cout<<"the "<<i+1<<" Number:";
    1142 cout<<stu[i].No<<endl;
    1143 cout<<"the "<<i+1<<" sex:";
    1144 cout<<stu[i].sex<<endl;
    1145 }
    1146 return 0;
    1147 }
    1148 
    1149 63、异常。
    1150 try(){throw 类型名;};
    1151 catch(类型变量)
    1152 {
    1153 };
    1154 做过选课系统的应该比较熟悉。
    1155 直接上实例。
    1156 //MyException.h
    1157 #include "stdafx.h"
    1158 class CMyException
    1159 {
    1160 public:
    1161 CMyException(string msg)
    1162 {
    1163 err_msg=msg;
    1164 };
    1165 virtual ~CMyException()
    1166 {
    1167 
    1168 };
    1169 void show()
    1170 {
    1171 cerr<<err_msg<<endl;
    1172 }
    1173 protected:
    1174 string err_msg;
    1175 };
    1176 //main.cpp
    1177 // C++速成.cpp : 定义控制台应用程序的入口点。
    1178 //
    1179 
    1180 #include "stdafx.h"
    1181 #include "MyException.h"
    1182 int _tmain(int argc, _TCHAR* argv[])
    1183 {
    1184 int type;
    1185 cout<<"plese insert the number of exception:1.int    2.float     3.double    4.selfdefine"<<endl;
    1186 cin>>type;
    1187 try{
    1188 switch(type)
    1189 {
    1190 case 4:
    1191 throw CsMyException("wrong!");//抛出自定义类异常
    1192 break;
    1193 case 1:
    1194 throw 1;//整形
    1195 break;
    1196 case 2:
    1197 throw 1.2f;//float
    1198 break;
    1199 case 3:
    1200 throw 1.23;//doubule
    1201 break;
    1202 default:
    1203 break;
    1204 }
    1205 }
    1206 
    1207 catch(CMyException a)
    1208 {
    1209 a.show();
    1210 }
    1211 catch(int b)
    1212 {
    1213 cerr<<"error int!";
    1214 }
    1215 catch(float c)
    1216 {
    1217 cerr<<"error float!";
    1218 }
    1219 catch(double d)
    1220 {
    1221 cerr<<"error double!";
    1222 }
    1223 return 0;
    1224 }
    1225 API编程:
    1226 64、API:Windows Application Programming Interface.
    1227 windows底层->win32 API函数->windows应用程序
    1228 句柄:本身为内存中一个占有4个字长的数值,用于标识应用程序中不同对象和相同对象的不同实例。句柄与普通指针的区别在于,指针包含的是引用对象的内存地址,而句柄则是由系统所管理的引用标识,该标识可以被系统重新定位到一个内存地址上。这种间接访问对象的模式增强了系统对引用对象的控制。
    1229 
    1230  
    1231 
    1232  
  • 相关阅读:
    LockFile文件-解决并发写入日志的问题
    二、Consul Service Mesh
    查看CPU和内存,用机器指令和汇编指令编程
    环境配置过程中的一些小tips
    工具使用指北:GDB
    瞧瞧我发现了什么
    新的目标:Capture The Flag
    python 实现的idw插值方法
    Python 利用 百度接口输入地点名字返回经纬度
    轻松搞定javascript变量(闭包,预解析机制,变量在内存的分配 )
  • 原文地址:https://www.cnblogs.com/chenzuoyou/p/3276338.html
Copyright © 2011-2022 走看看