主要是为了学习c++的类和对象
 
内容摘自 c++概述
http://see.xidian.edu.cn/cpp/biancheng/cpp/rumen_1/
 
1,变量 
,C++中,我们可以在函数体内声明一个静态局部变量(Static Local Variable)。它在函数运行结束后不会消失,并且只有声明它的函数中能够使用它。我们可以在函数体外声明一个变量,它称为全局变量(global variable),在某一层次声明的变量的作用域就终止于该变量所在层次的末尾。在某个函数的同一语法层次内不能声明多个名字相同的变量。在函数体内声明一个静态局部变量(Static Local Variable)。它在函数运行结束后不会消失,并且只有声明它的函数中能够使用它(static int a;)。
2,逻辑
if (m!=0 && n/m<1),当m=0时,电脑不会去尝试用n/m了,而是直接跳过整句语句。这样,我们就能够避免除数为零的错误了
“……?……:……”称为条件操作符,它的运算优先级比逻辑或还低,是目前为止优先级最低的操作符, max=(a>=b)?a:b;
在switch语句中,我们要记住四个关键词,分别是switch、case、default和break。
switch(表达式)
{
   case 常量表达式1:
   {
      语句块1;
      break;
   }
   default:
   {
      语句块n+1;
   }
}
cout <<setw(2) <<a <<b;语句中域宽设置仅对a有效,对b无效。
3,函数
一旦函数运行结束,那么该函数中声明的参数和变量都将消失。
return 符合返回值类型的表达式;
在返回空类型的函数中可以使用return语句,人为地停止函数的运行,也可以不使用return语句,使其运行完所有语句后自然停止。
4,存储
在定义默认参数时,必须在函数声明中定义
void create(int n=100);//在函数声明中定义默认参数
int size=sizeof(array)/sizeof(int);//数组的大小
数组作为参数传递给函数的只是数组首元素的地址,函数在需要用到后面元素时再按照这个地址和数组下标去查找
指针和整数C的加减法是指针向前或向后移动C个对应类型的存储区域
数组名是指针,但它是一个指针常量。也就是说,不带下标的数组名不能作为左值。
数组的大小在编译前必须是已知的常量表达式
不同于数组,结构是按值传递的。也就是说整个结构的内容都复制给了形参,即使某些成员数据是一个数组。使用返回结构体方式实现修改
5,调试
用函数声明和定义分离的方式:把所有的声明都放在shape.h中,把所有的定义放在shape.cpp中
#开头的命令都是编译预处理命令,比如#if、#else、#endif、#ifdef、#ifndef、#undef和#define
无论这个文件是C++提供的还是自己编写的,使用#include "文件名"命令一定是正确的
如果包含头文件时写作如#include <iostream>,但是没有using namespace std;必须要使用std名字空间。
在编译阶段发生的错误称为编译错误(Compile Error),在运行阶段发生的错误称为运行时错误(Runtime Error)。对于编译错误,我们通过检查并修正语法错误来解决;对于运行时错误,我们通过检查并修正语意(程序设计思想)错误来解决
6,对象
面向对象(Object Oriented,简称OO)
对象就是任何我们可以想象出来的具体的物体
能够抽象地描述某一些具有共性的物体的词称为类(Class)
类与结构相似,它也是一种由用户自己定义的数据类型;它也可以通过成员数据来刻画一些现实生活中的东西。不同的是,对它的操作并不是通过普通的函数,而是通过类的成员函数来实现的
定义完一个类之后务必要在最后加上一个分号。
类中变量在定义或声明时不说明该成员数据(或成员函数)是公有的还是私有的,则默认为私有的。
class Node//定义一个链表结点类
{
   public:
   int idata;//数据能够被外部访问
   char cdata;//数据能够被外部访问
   private:
   Node *prior;//前驱结点的存储位置保密
   Node *next;//后继结点的存储位置保密
};
如果一个类的某个成员函数是私有的,那么它只能被这个类的其他成员函数调用。
const这个保留字来保护成员数据不被成员函数改变
成员函数的写法就是在函数的参数表后面加上一个const,比如:int readi() const;//通过该函数读取idata,但不能改变任何成员数据
"::"操作符,它表示该函数是属于某一个类的,称为域解析操作符
定义类成员函数
//node.h
class Node//定义一个链表结点类
{
   public:
   int readi() const;//通过该函数读取idata,但不能改变任何成员数据
   bool set(int i);//重载,通过该函数修改idata
   bool set(char c);// 重载,通过该函数修改cdata
   private:
   int idata;//存储数据保密
   char cdata;//存储数据保密
};//类定义结束,分号切勿忘记
int Node::readi() const   //成员函数readi的定义
{
   return idata;
}
bool Node::set(int i)//重载成员函数定义
{
   idata=i;
   return true;
}
bool Node::set(char c)
{
   cdata=c;
   return true;
}
调用成员函数
//main.cpp
#include <iostream>
#include "node.h"//包含我们编写好的链表结点类头文件,必须用双引号
using namespace std;
int main()
{
   Node a;//创建一个链表结点对象a
   a.set(1);//设置idata
   a.set('A');//设置cdata
   cout <<a.readi() <<endl;
   cout <<a.readc() <<endl;
   return 0;
}
对象的引用
   Node b;//声明一个结点对象
   Node &a=b;//声明一个引用
   a.set(0);//效果与b.set(0)相同
对象指针
   Node b;//声明一个结点对象
   Node *a=&b;//声明一个对象指针
   a->set(0);//效果与b.set(0)相同
   a->readi();//效果与b.readi()相同
对象的初始化的方法,增加初始化函数 void init(type,type);
构造函数是一种随着对象创建而自动被调用的函数,与类同名的成员函数就是构造函数,它的主要用途是为对象作初始化,它是一个公有的成员函数,并且构造函数没有返回值类型。
class Node//定义一个链表结点类
{
   public:
   Node();//构造函数的声明,构造函数是公有的成员函数,没有返回值类型
   private:
   int idata;//存储数据保密
   char cdata;//存储数据保密
};
Node::Node() //构造函数的定义
{
   cout <<"Node constructor is running..." <<endl;//提示构造函数运行
   idata=0;//初始化idata
   cdata='0';//初始化cdata
}
带参数的构造函数(构造函数也可以重载)
Node::Node(int i,char c)//构造函数重载1,默认参数只需要在函数原型中出现
{
   cout <<"Node constructor is running..." <<endl;
   idata=i;
   cdata=c;
   prior=NULL;
   next=NULL;
}
 对应于main中的,Node b(8);//创建一个链表结点对象b,调用构造函数重载1,参数c默认为'0'
在C++中,每个类都有且必须有构造函数。如果用户没有自行编写构造函数,则C++自动提供一个无参数的构造函数,称为默认构造函数。这个默认构造函数不做任何初始化工作。一旦用户编写了构造函数,则这个无参数的默认构造函数就消失了。如果用户还希望能有一个无参数的构造函数,必须自行编写
深拷贝构造函数是真正意义上的复制了链表a,并且使得链表a和链表b各自独立,互不干扰。这才是自定义拷贝构造函数存在的重要意义
//拷贝构造  
 CExample(const CExample& C)  
 {  
  a = C.a;  
  cout<<"copy"<<endl;  
 }  
CExample B = A; // CExample B(A); 也是一样的,这里不是赋值
析构函数(Destructor)能随着对象的消亡而自动被调用
对象作为函数参数时,会先调用对象的拷贝构造函数,把参数的值复制给临时对象,函数结束后,临时对象调用析构函数
构造函数用于初始化对象,拷贝构造函数用于访问创建的对象,用于类向对象中的似有成员传递指
对象rect1的p和rect2的指针成员p各自指向一段内存空间,但它们指向的空间具有相同的内容,这就是所谓的“深拷贝”
初始式example
#include "iostream"
#include "stdlib.h"
using namespace std;
 
class A
{
public:
A(int i,char c);
void show();
private:
int idata;
char cdata;
};
A::A(int i,char c)
{
idata=i;
cdata=c;
}
void A::show()
{
cout <<"A.show"<<endl<<idata<<endl;
cout<<cdata<<endl;
cout<<"A.show end"<<endl;
}
class B
{
public:
B(int i,char c);
void show();
private:
int bint;
A ao;
A *p;
char bchar;
};
B::B(int i,char c):ao(i,c)
{
cout<<"B copy and creat"<<endl;
cout<<i<<c<<endl;
p=&ao;
cout<<"B copy and creat end"<<endl;
 }
void B::show()
{
cout<<"B.show begin"<<endl;
p->show();//或者ao.show();
cout<<"B.show end"<<endl;
}
int main()
{
A a(1,'a');
a.show();
B b(2,'b');
b.show();
system("pause");
}
如果指针指向不是用 new 分配的内存地址,则在该指针上使用 delete 是不合法的。
const int *pci = new const int(1024);
动态创建的 const 对象必须在创建时初始化,并且一经初始化,其值就不能再修改。
由new生成的ptemp,在执行delete之后,还可以对其进行赋值操作,猜想delete 操作删除的是指针指向内存的内容
 
一个类成员中有其他类对象,可以用以下方式构造(linklist成员中有node类,pucurrent和head分别为node类的对象和对象指针
方式一
Linklist::Linklist(int i,char c):head(i,c)//类名::构造函数名(参数表):成员对象名1(参数表),链表类构造函数,调用head对象的构造函数重载1,详见Node.h文件
{
   cout<<"Linklist constructor is running..."<<endl;
   pcurrent=&head;
}
方式二,需要在node类中声明linklist是友元类,friend class Linklist;
Linklist::Linklist(Linklist &l):head(l.head)
{
   cout<<"Linklist Deep cloner running..." <<endl;
   pcurrent=&head;
   Node * ptemp1=l.head.next;//直接访问私有成员数据
while(ptemp1!=NULL)//复制链表
   {
      Node * ptemp2=new Node(ptemp1->idata,ptemp1->cdata,pcurrent,NULL);
      pcurrent->next=ptemp2;
      pcurrent=pcurrent->next;
      ptemp1=ptemp1->next;
}
 
一个函数要访问一个或多个对象的私有成员时,我们可以用友元来解决这个问题。
friend void ShowNode(Node &n);//声明友元函数ShowNode,在节点类中声明
在main函数中可以使用ShowNode(b);//用友元函数输出b结点的内容
 
操作符重载,a是复数
void Complex::operator =(Complex a)
{
   real=a.real;
   img=a.img;
}
Complex Complex::operator +(Complex a)
{
   Complex temp(a.real+real,a.img+img);
   return temp;
}
这样在main函数中,可以进行操作
Complex a(3,2),b(5,4),c(1,1),d(4,2),temp;
   temp=a+b;
 
继承的方法,使我们可以用一种已经编写好的类来扩写成一个新的类
class 子类名:[public,private,protect]父类名;
private(私有)和protected(保护)都能实现类的封装性。private能够对外部和子类保密,即除了成员所在的类本身可以访问之外,别的都不能直接访问。protected能够对外部保密,但允许子类直接访问这些成员。
 
private是私有继承父类所有的公有、保护成员继承到子类时,类型会发生改变。父类的公有成员在子类中变成了私有成员,父类的保护成员在子类中也变成了私有成员。父类不能在访问子类中成员
 
class Stack:private Linklist//私有继承链表类
void Stack::show()
{
Show();//用Linklist类的成员函数实现功能
}
父类的成员对象是最先构造的,接着是运行父类的构造函数,最后运行子类的构造函数。
子类的构造函数的参数传递给父类的构造函数
Stack::Stack(int i,char c):Linklist(i,c)//将子类构造函数的参数传递给父类的构造函数
{
   cout <<"Stack constructor with parameter is running..." <<endl;
}
使用了继承之后,析构函数的运行顺序依然恰好与构造函数的运行顺序相反。
 
父类指针能否指向子类对象?子类指针能否指向父类对象?
在公有继承情况下父类的对象指针指向子类对象是允许的。子类的对象指针指向父类是禁止的
用父类的对象指针指向子类对象,那么这个指针无法使用子类中扩展出的成员。
 
子父类例子
如果有一个本科生对象s1和一个学生对象s2,那么显然s1.study()会是学习高等数学和大学英语,s2.study()会是随便学些什么。但是,如果有一个学生类的指针sp,它也能指向本科生对象,这时调用sp->study()会是怎么样的呢?我们发现,即使它指向一个本科生对象,它也只能“随便学些什么”。
 
不同的子类的同名成员函数有着不同的表现形式,称为多态性
多态性往往只有在使用对象指针或对象引用时才体现出来。多态性是面向对象的一个标志性特点,没有这个特点,就无法称为面向对象。
 
设置虚函数的方法为:在成员函数的声明最前面加上保留字virtual。注意,不能把virtual加到成员函数的定义之前,否则会导致编译错误。
 
virtual void study();//把学习设置为虚函数,父类中
void student::study()//成员函数定义处没有virtual
{
   cout <<"随便学些什么。" <<endl;
   return;
}
virtual void study();//把学习设置为虚函数,父类的一个子类中class Undergraduate:public student
void Undergraduate::study()//成员函数定义处没有virtual
{
   cout <<"学习高等数学和大学英语。" <<endl;
   return;
}
 virtual void study();//把学习设置为虚函数,父类的一个子类中class Pupil:public student
void Pupil::study()
{
   cout <<"学习语数外。" <<endl;
   return;
}
main函数中
 Undergraduate s1;
   student s2;
   Pupil s3;
student *sp
无论父类对象指针sp指向哪种子类对象,sp->study()的执行结果总是与对应的类相符合的
要使用虚函数实现多态性,至少要使各个函数的参数格式也完全相同。
当子类函数和父类参数不同时,会执行父类中的同名成员函数
编写成员函数的时候,可以把尽可能多的成员函数设置为虚函数。
 
给析构函数的前面加上保留字virtual, virtual ~Animal();//虚析构函数,父类animal中
子类中
Cat::~Cat()
{
   cout <<"Cat destructor is running..." <<endl;
}
main中
Animal *pa=new Cat(2,1);
   Cat *pc=new Cat(2,4);
delete pa;
   delete pc;
结果:
Cat constructor is running...
Animal consturctor is running...
Cat constructor is running...
Delete pa:
Cat destructor is running...
Animal destructor is running...
Delete pc:
Cat destructor is running...
Animal destructor is running...
子类和父类的析构函数都被执行
虚函数是为了实现多态,而虚析构函数是为了同时运行父类和子类的析构函数,使资源得以释放。
 
只能用于被继承而不能直接创建对象的类设置为抽象类(Abstract Class)。
类中的确存在,但是在父类中无法确定具体实现的成员函数称为纯虚函数。纯虚函数是一种特殊的虚函数,它只有声明,没有具体的定义。抽象类中至少存在一个纯虚函数;存在纯虚函数的类一定是抽象类。
 
设置纯虚函数之后并不影响多态的实现,但是却将父类变成了抽象类,限制了父类对象的创建,virtual void study()=0;//在父类的声明中通过代码实现,声明study为纯虚函数
 

C++ note的更多相关文章

  1. 三星Note 7停产,原来是吃了流程的亏

    三星Note 7发售两个月即成为全球噩梦,从首炸到传言停产仅仅47天.所谓"屋漏偏逢连天雨",相比华为.小米等品牌对其全球市场的挤压.侵蚀,Galaxy Note 7爆炸事件这场连 ...

  2. 《Note --- Unreal --- MemPro (CONTINUE... ...)》

    Mem pro 是一个主要集成内存泄露检测的工具,其具有自身的源码和GUI,在GUI中利用"Launch" button进行加载自己待检测的application,目前支持的平台为 ...

  3. 《Note --- Unreal 4 --- Sample analyze --- StrategyGame(continue...)》

    ---------------------------------------------------------------------------------------------------- ...

  4. [LeetCode] Ransom Note 赎金条

    
Given
 an 
arbitrary
 ransom
 note
 string 
and 
another 
string 
containing 
letters from
 all 
th ...

  5. Beginning Scala study note(9) Scala and Java Interoperability

    1. Translating Java Classes to Scala Classes Example 1: # a class declaration in Java public class B ...

  6. Beginning Scala study note(8) Scala Type System

    1. Unified Type System Scala has a unified type system, enclosed by the type Any at the top of the h ...

  7. Beginning Scala study note(7) Trait

    A trait provides code reusability in Scala by encapsulating method and state and then offing possibi ...

  8. Beginning Scala study note(6) Scala Collections

    Scala's object-oriented collections support mutable and immutable type hierarchies. Also support fun ...

  9. Beginning Scala study note(5) Pattern Matching

    The basic functional cornerstones of Scala: immutable data types, passing of functions as parameters ...

  10. Beginning Scala study note(4) Functional Programming in Scala

    1. Functional programming treats computation as the evaluation of mathematical and avoids state and ...

随机推荐

  1. egrep 查找IP

    1. egrep '([^0-9]|\<)(([0-1]?[0-9]{0,2}|([2]([0-4][0-9]|[5][0-5])))\.){3}([0-1]?[0-9]{0,2}|([2]([ ...

  2. but this usually doesn’t gain you anything.

    High Performance My SQL, Third Edition Date and Time Types My SQL has many types for various kinds o ...

  3. Static Random-Access Memory Dynamic Random-Access Memory

    COMPUTER ORGANIZATION AND ARCHITECTURE DESIGNING FOR PERFORMANCE NINTH EDITION RAM technology is div ...

  4. getWindow().setFlags

    //设置窗体全屏 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams ...

  5. [dpdk] 读官方文档(3)

    续前节, 测试小程序 1. 想编译测试程序首先需要设置两个环境变量,为什么呢,因为测试程序的Makefile里用了... rpm装了打包好的devel包,这个rpm也会自带这两个环境变量.就是说写第三 ...

  6. AppleScript

    一.资源 1.书本 2.ide: AppleSreipt Editor 3.界面辅助软件: UIBrowser 破解方法: a) ui browser -> show package conte ...

  7. 记录下 QT Linux 静态编译遇到的坑

    Qt下静态编译Qt,根据我的经验,如果按照Windows下那种直接拿官方sdk安装之后的文件来编译是行不通的,需要直接下载Qt的source包,目前诺基亚的源码叫做qt-everywhere-open ...

  8. 利用VS编译libiconv库

    参考文章:http://blog.csdn.net/ghevinn/article/details/9834119 关于中文字符编码问题,这篇文章里面讲的很详细-->http://www.tui ...

  9. php--validate表单验证

    validate表单验证扩展规则 添加自定义检验(验证class) 获取html加入 class <input id="D_NUMBER" name="D_NUMB ...

  10. 一些html页面资料

    一下没有什么重要的,只是我平时积累的一些页面,紧急时或许会有用,相信过一段时间去东宇(公司分公司)了,这些资料页带不走,还不如留在博客里,趁组长级别们开会去了,他们已经开了一个点啦!我的组长去东宇查看 ...