继承的几个测试
来源:互联网 发布:tenga 根沐 知乎 编辑:程序博客网 时间:2024/06/05 16:58
c++好多年不学了。
突然捡起来,非常的不适应,不仅仅是头疼,而是当年学的粗浅,任何概念都不深入。只好测一测。
===========
静态的成员函数,可以被子类覆盖么?
我也不知道这算不算覆盖。
#include <iostream>using namespace std;class base {public: static int statFun(){cout << "in class base"<<endl;} //......};class derived1:public base{ //......};class derived2:public base{public: static int statFun(){cout << "in class derived2"<<endl;} //......};int main(int argc, char *argv[]){ base::statFun(); //父类自身的 derived1::statFun(); //父类的 derived2::base::statFun(); //父类的 derived2::statFun(); //自身的 system("pause"); return 0;}
可以看到子类1继承了父类的静态函数。
子类2覆盖了父类的静态函数,用 的自己的。
所以说,静态函数可以被子类继承,也可以被子类覆盖。
=======================================
参考http://blog.csdn.net/taina2008/article/details/1684834
这是一个多继承的例子。
#include<iostream>using namespace std;class Employee {//职工 public: void skill()//职工技能 { cout<<"我的skill水平就是Employee"<<endl; }}; class Technical: public Employee {//技术,也是职工 }; class Manager: public Employee {//经理,也是职工 }; class TechnicalManager:public Technical,public Manager {//技术经理,也是职工 }; int main(int argc, const char * argv[]){ TechnicalManager tManager; /* 28 E:\codeReocrdi\test.cpp request for member `skill' is ambiguous error E:\codeReocrdi\test.cpp:8 candidates are: void Employee::skill() 8 E:\codeReocrdi\test.cpp void Employee::skill() */ //tManager.skill();//此处编译错误 tManager.Technical::skill(); tManager.Manager::skill(); system("pause"); return 0;}可以看到多继承下的子类,会在内存中有两份父类的方法的拷贝,编译器不知道该选择啥了。
但是如果指定了其某个父类的方法,就可以顺利输出了。
===========================================================
继承的时候,先调用父类的构造函数,然后是子类的构造函数。
#include <iostream.h> using namespace std;class animal { public: animal(int height, int weight) { cout<<"animal construct"<<endl; } }; class fish:public animal { public: fish():animal(400,300) { cout<<"fish construct"<<endl; }}; int main() { fish fh; system("pause"); return 0;}
而且如果有带有参赛的构造函数,必须在构造函数中用:父类名(初始值)方式显示初始化父类构造函数。
比如MediaSource的构造函数,显示调用了父类Medium的有参数构造函数:
参考http://blog.csdn.net/hemmingway/article/details/7853713
构造方法用来初始化类的对象,与父类的其它成员不同,它不能被子类继承(子类可以继承父类所有的成员变量和成员方法,但不继承父类的构造方法)。因此,在创建子类对象时,为了初始化从父类继承来的数据成员,系统需要调用其父类的构造方法。
如果没有显式的构造函数,编译器会给一个默认的构造函数,并且该默认的构造函数仅仅在没有显式地声明构造函数情况下创建。
有个原则,参考http://blog.csdn.net/hemmingway/article/details/7853713
1. 如果子类没有定义构造方法,则调用父类的无参数的构造方法。
2. 如果子类定义了构造方法,不论是无参数还是带参数,在创建子类的对象的时候,首先执行父类无参数的构造方法,然后执行自己的构造方法。
3. 在创建子类对象时候,如果子类的构造函数没有显示调用父类的构造函数,则会调用父类的默认无参构造函数。
4. 在创建子类对象时候,如果子类的构造函数没有显示调用父类的构造函数且父类自己提供了无参构造函数,则会调用父类自己的无参构造函数。
5. 在创建子类对象时候,如果子类的构造函数没有显示调用父类的构造函数且父类只定义了自己的有参构造函数,则会出错(如果父类只有有参数的构造方法,则子类必须显示调用此带参构造方法)。
6. 如果子类调用父类带参数的构造方法,需要用初始化父类成员对象的方式
============================================================
temp.某函数();
子类 temp * =new 子类();
temp.某函数();
#include <iostream> using namespace std;//虚函数继承: class A { public: virtual void fun() {cout <<'A' <<endl;}; }; class B : public A { public: virtual void fun() {cout <<'B' <<endl;}; }; int main(int argv, char** argc) { A *a=new A; a->fun(); //A A* p = new B; p->fun(); //结果输出B,而不是A,至于实现原理,其实是对象头部多了四个字节,它是一个指向虚函数表的地址指针,程序运行时通过这个表,找到了这个B::fun()的入口地址 B* b=new B; b->fun(); //B system("pause"); return 0; }
参考http://alice-2860.blog.163.com/blog/static/490180162009975245293/
比如类A有个就是a,B继承了A,C也继承了A,当D多继承B,C时,就会有歧义产生了,所以要使用虚拟继承避免重复拷贝。
虚函数继承是解决多态性的,当用基类指针指向派生类对象的时候,基类指针调用虚函数的时候会自动调用派生类的虚函数,这就是多态性,也叫动态编联
下面的这个例子里,父类有一个虚函数,子类没有虚函数,但是子类有一个和父类的这个虚函数同名的函数。
当
父类的指针指向子类对象时,声明为virtual的父类虚函数1不会执行,执行的是是子类同名的非virtual函数1。
而父类非virtual的函数2会执行,不执行子类非virtual的函数2.
如下:
#include <iostream> using namespace std;//虚函数继承:class parent { public: virtual void foo(){cout <<"foo from parent"<<endl;}; void foo1(){cout <<"foo1 from parent";}; }; class son:public parent { void foo(){cout <<"foo from son"<<endl;}; void foo1(){cout <<"foo1 from son"<<endl;}; }; int main() { parent *p=new son(); p->foo(); //son p->foo1();//parent system("pause"); return 0; }
难道是可以这么认为:
只有父类virtual的函数,才会有多态发生在子类上?
多态:
参考
http://blog.csdn.net/bao_jinyu/article/details/7843275
1.1 多态
在了解了虚函数的意思之后,再考虑什么是多态就很容易了。仍然针对上面的类层次,但是使用的方法变的复杂了一些:
foo()是类A的虚函数,那么:
void bar(A * a)
{
a->foo(); // 被调用的是A::foo() 还是B::foo()?
}
因为foo()是个虚函数,所以在bar这个函数中,只根据这段代码,无从确定这里被调用的是A::foo()还是B::foo(),但是可以肯定的说:如果a指向的是A类的实例,则A::foo()被调用,如果a指向的是B类的实例,则B::foo()被调用。
===========================
再加一个,可以得到这样的结论:
对于父类的virtual,如果去掉virtual就跟普通的函数一样,加了virtual就可以用多态机制。
如果子类重写了,则只用子类的实现
#include <iostream> using namespace std;//虚函数继承:class parent { public: virtual void foo(){cout <<"foo from parent"<<endl;}; void foo1(){cout <<"foo1 from parent"<<endl;}; }; class son:public parent { public: void foo(){cout <<"foo from son"<<endl;}; void foo1(){cout <<"foo1 from son"<<endl;}; }; int main() { parent *p=new son(); p->foo(); //son p->foo1();//parent son *s=new son; s->foo(); //son s->foo1();//son system("pause"); return 0; }
子类完全可以无视父类的virtual
======================================================
- 继承的几个测试
- 关于继承的几个误区
- 测试的几个误区
- 几个测试的基本概念
- 几个测试的基本概念
- 测试的几个方面
- 继承下的几个概念的区别
- 关于测试的几个术语
- indy UDP的几个测试
- 几个经典的测试文档
- javamail的几个测试程序!
- 几个很“高雅”的测试
- 几个浏览器的H5测试
- 测试相关的几个概念
- 性能测试的几个术语
- 软件测试的几个误区
- 软件测试的几个误区
- 测试几个xml的问题
- 并发程序块
- Android_ViewPager_图片自动翻转
- shell中的比较
- Dialog 开发简介
- 怎样在VS2010中打开VS2012的项目
- 继承的几个测试
- MMS 收发
- java中使用sax解析xml的解决方法
- hangzhou 02
- 输出GBK所有编码及其代表的字符
- 黑马程序员_银行业务调度系统
- cocos2d-x CSV文件读取 (Excel生成csv文件)
- 用谷歌浏览器来当手机模拟器
- mapreduce调试