点滴记录C++

来源:互联网 发布:c语言的创始人 编辑:程序博客网 时间:2024/06/06 01:46

 

 

 

 

---------------------------------------------------

两个冒号::的用法

如:
class Generic_GCC
{
public:
   class GCCInstallationDetector
   {
   public:
      static void ScanLibDirForGCCTriple();
   }
};
调用就是  Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple();

还有就是 namespace

 

-----------------------------------------------

匿名 namespace 用法:

即: namespace {

xxxxxxx

...

}

用法:

namespace{}, 一般用来隔离代码,比如你在同一个文件中需要定义两个同名的函数,这两个函数又相互没关系,可以分别用一个匿名namespace括起来,每个函数只在自己的空间中有效;
又如你不希望外部的函数看到你定义的函数或者变量,也可以用匿名空间,这样外部的函数无法调用匿名空间中的函数或者变量

 

 -----------------------------------------------------------------------------

 C++ 中的struct

http://blog.csdn.net/xdrt81y/article/details/17143801

struct  与 class 区别:

最本质的一个区别就是默认的访问控制。

默认的继承访问权限。struct是public的,class是private的。

到底默认是public继承还是private继承,取决于子类而不是基类。我的意思是,struct可以继承class,同样class也可以继承struct,那么默认的继承访问权限是看子类到底是用的struct还是class。如下:

    struct A{};

    class B : A{};    //private继承

    struct C : B{};  //public继承

 

struct作为数据结构的实现体,它默认的数据访问控制是public的,而class作为对象的实现体,它默认的成员变量访问控制是private的。

--------------------------------------------------

virtual(虚)  与 abstract(抽象)

http://blog.csdn.net/weiwenhp/article/details/6969463

 

classabstract修饰了,里面的成员才能被abstract修饰.  (正能量:真心英雄)—— 抽象类不能被实例化.

virtual不能用来修饰class.只能用来修饰其中的成员.virtual可用于一般的class中,也可用于被abstract修饰的抽象类中

 

抽象方法里面是啥都没有的.只有个方法的定义在那,不能在里面去实现任何功能,然后必须在继承的子类中重写了才能用。

而virtual方法不能只是个定义必须要实现.在继承的子类中可以被重写然后再用,也可以不重写直接用,用法和一般方法一样。

 作用:?

 虚方法和抽象方法可以用来实现多态

 抽象类是实现和接口类似的功能  

因此, 纯虚函数 ,不能用abstract代替,因为virtual是用来实现多态的。(zlg)

侧重有所不同。 

 

我们知道面向对象的最主要的三个特性就是封装,继承,多态。

多态简单的说就是通过继承创建的多个class,调用相同的方法(即返回类型,方法名,参数列表都相同.)实现了不同的功能.(即顾名思义:多态)

它是通过在继承中重写(override)相同的方法实现的.

 

接口与抽象类有些相同的地方:

1.不能实例化  2.具有没有实现的方法.3.只有被继承的子类实现了没实现的方法才能实例化

不同点:

1.抽象类也是一种特殊的类.所有也只能单继承.接口则可以多继承

2.接口中的方法不能被public,private等修饰符修饰.它默认是为public.

3.接口除了可以包含方法之外,还可以包含属性、索引器、事件,而且这些成员都被定义为公有的。除此之外,不能包含任何其他的成员,例如:常量、域、构造函数、析构函数、静态成员

4.接口中的方法都不能实现.而抽象类可以实现一部分方法或者全部实现.就跟一般的class一样.

 

-----------------------------------------------------------------------------------------

http://blog.csdn.net/chn_cf/article/details/6798885

与覆盖的区别
1、方法的覆盖是子类和父类之间的关系,是垂直关系;方法的重载是同一个类中方法之间的关系,是水平关系
2、覆盖要求参数列表相同;重载要求参数列表不同
3、覆盖关系中,调用那个方法体,是根据对象的类型(对象对应存储空间类型)来决定;重载关系,是根据调用时的实参表与形参表来选择方法体的。

 

-----------------------------------------------------------------------------------------------------

抽象类:

http://blog.csdn.net/tang_ming/article/details/5826842

 

抽象类

    带有纯虚函数的类称为抽象类。抽象类是一种特殊的类,它是为了抽象和设计的目的而建立的,它处于继承层次结构的较上层。抽象类是不能定义对象的,在实际中为了强调一个类是抽象类,可将该类的构造函数说明为保护的访问控制权限。

    抽象类的主要作用是将有关的组织在一个继承层次结构中,由它来为它们提供一个公共的根,相关的子类是从这个根派生出来的。

    抽象类刻画了一组子类的操作接口的通用语义,这些语义也传给子类。一般而言,抽象类只描述这组子类共同的操作接口,而完整的实现留给子类。

    抽象类只能作为基类来使用,其纯虚函数的实现由派生类给出。如果派生类没有重新定义纯虚函数,而派生类只是继承基类的纯虚函数,则这个派生类仍然还是一个抽象类。如果派生类中给出了基类纯虚函数的实现,则该派生类就不再是抽象类了,它是一个可以建立对象的具体类了。

 

-------------------------------------------------------------------------

 什么是 真正的 多态呢??

 

虚函数必须是基类的非静态成员函数,其访问权限可以是protected或public,在基类的类定义中定义虚函数的一般形式:  

     virtual 函数返回值类型 虚函数名(形参表)
         { 函数体 }
     虚函数的作用是实现动态联编(普通成员函数没有这个功能,只能简单的调用与重写),也就是在程序的运行阶段动态地选择合适的成员函数,在定义了虚函数后,可以在基类的派生类中对虚函数重新定义,在派生类中重新定义的函数应与虚函数具有相同的形参个数和形参类型。以实现统一的接口,不同定义过程。如果在派生类中没有对虚函数重新定义,则它继承其基类的虚函数。
     即实现多态性(Polymorphism),多态性是将接口与实现进行分离;用形象的语言来解释就是实现以共同的方法,但因个体差异而采用不同的策略。 

  动态联编规定,只能通过指向基类的指针或基类对象的引用来调用虚函数
其格式:  
指向基类的指针变量名->虚函数名(实参表)
基类对象的引用名. 虚函数名(实参表) 
http://blog.csdn.net/BEN1978/article/details/734909
 

条件

  所以,从以上程序分析,实现动态联编需要三个条件:
  1、 必须把动态联编的行为定义为类的虚函数。
  2、 类之间存在子类型关系,一般表现为一个类从另一个类公有派生而来。
 
  3、 必须先使用基类指针指向子类型的对象,然后直接或者间接使用基类指针调用虚函数。
 

举个多态的简单例子吧:

//基类:

public class  Person

{

public virtual void Do()

{

Console.WriteLine("Do something");

}

}

//继承的类:

public class  Cheater:Person

{

public override void Do()

{

Console.WriteLine("Go to take money from some  fools");

}

}

public class  Killer:Person

{

public override void Do()

{

Console.WriteLine("Go to kill somebody");

}

}

Class PersonDo--测试类
   {
     Static void
Main(string[] args)

   {

Person cheater = new Cheater();

cheater.Do();

Person killer = new Killer();

killer.Do();

}
}

--结果为:Go to take money from some  fools

--           Go to kill somebody    

   
我们也可以把基类改成抽象类,继承子类不变.运行结果跟上面一样.

public abstract class  Person

{

public abstract void Do();

}

------简单的多态例子结束。--
 class A{
  public:
 
  void print(){ cout<<”This is A”<<endl;}
 
  };
 
 class B:public A{
 
  public:
 
  void print(){ cout<<”This is B”<<endl;}
 
  };
  int main(){ //为了在以后便于区分,我这段main()代码叫做main1
 
  A a;
  B b;
  a.print();
  b.print();
  }
  通过class A和class B的print()这个接口,可以看出这两个class因个体的差异而采用了不同的策略,输出的结果也是我们预料中的,分别是This is A和This is B。但这是否真正做到了多态性呢?No,多态还有个关键之处就是一切用指向基类的指针或引用来操作对象。那现在就把main()处的代码改一改。
 
  int main(){ //main2
 
  A a;
 
  B b;
 
  A* p1=&a;
 
  A* p2=&b;
 
  p1->print();
 
  p2->print();
 
  }
 
  运行一下看看结果,哟呵,蓦然回首,结果却是两个This is A。问题来了,p2明明指向的是class B的对象但却是调用的class A的print()函数,这不是我们所期望的结果,那么解决这个问题就需要用到虚函数
  class A{
 
  public:
  virtual void print(){ cout<<”This is A”<<endl;} //现在成了虚函数了
  };
  class B:public A{
  public:
  void print(){ cout<<”This is B”<<endl;} //这里需要在前面加上关键字virtual吗?
  };
 
  毫无疑问,class A的成员函数print()已经成了虚函数,那么class B的print()成了虚函数了吗?回答是Yes,我们只需在把基类的成员函数设为virtual,其派生类的相应的函数也会自动变为虚函数。所以,class B的print()也成了虚函数。那么对于在派生类的相应函数前是否需要用virtual关键字修饰,那就是你自己的问题了。
 
  现在重新运行main2的代码,这样输出的结果就是This is A和This is B了。
 
  现在来消化一下,我作个简单的总结,指向基类的指针在操作它的多态类对象时,会根据不同的类对象,调用其相应的函数,这个函数就是虚函数。
 
  使用虚函数,我们可以灵活的进行动态绑定,当然是以一定的开销为代价。如果父类的函数(方法)根本没有必要或者无法实现,完全要依赖子类去实现的话,可以把此函数(方法)设为virtual 函数名=0 我们把这样的函数(方法)称为纯虚函数。

 

 

0 0