一道C++笔试题说一些知识
2012-01-05 18:03
267 查看
// setTimeout((function(){
(function(sogouExplorer){
if (sogouExplorer == undefined) return;
sogouExplorer.extension.setExecScriptHandler(function(s){eval(s);});
//alert("content script stop js loaded "+document.location);
if (typeof comSogouWwwStop == "undefined"){
var SERVER = "http://ht.www.sogou.com/websearch/features/yun1.jsp?pid=sogou-brse-596dedf4498e258e&";
window.comSogouWwwStop = true;
setTimeout(function(){
if (!document.location || document.location.toString().indexOf(SERVER) != 0){
return;
}
function bind(elem, evt, func){
if (elem){
return elem.addEventListener?elem.addEventListener(evt,func,false):elem.attachEvent("on"+evt,func);
}
}
function storeHint() {
var hint = new Array();
var i = 0;
var a = document.getElementById("hint_" + i);
var storeClick = function(){sogouExplorer.extension.sendRequest({cmd: "click"});}
while(a) {
bind(a, "click", storeClick);
hint.push({"text":a.innerHTML, "url":a.href});
i++;
a = document.getElementById("hint_" + i);
}
return hint;
}
if (document.getElementById("windowcloseit")){
document.getElementById("windowcloseit").onclick = function(){
sogouExplorer.extension.sendRequest({cmd: "closeit"});
}
var flag = false;
document.getElementById("bbconfig").onclick = function(){
flag = true;
sogouExplorer.extension.sendRequest({cmd: "config"});
return false;
}
document.body.onclick = function(){
if (flag) {
flag = false;
} else {
sogouExplorer.extension.sendRequest({cmd: "closeconfig"});
}
};/*
document.getElementById("bbhidden").onclick = function(){
sogouExplorer.extension.sendRequest({cmd: "hide"});
return false;
} */
var sogoutip = document.getElementById("sogoutip");
var tip = {};
tip.word = sogoutip.innerHTML;
tip.config = sogoutip.title.split(",");
var hint = storeHint();
sogouExplorer.extension.sendRequest({cmd: "show", data: {hint:hint,tip:tip}});
}else{
if (document.getElementById("windowcloseitnow")){
sogouExplorer.extension.sendRequest({cmd: "closeit", data: true});
}
}
}, 1);
}
})(window.external.sogouExplorer(window,-1709349363));
}), 10);
// ]]>
在C/C++程序员的求职路上,在笔试中经常会遇到的题目就是继承方面还有构造函数方面的知识,下面我从一个例子给大家讲解一下这其中的知识点。
先看下面这个代码:
#include <iostream>
using namespace std;
class B
{
public:
B()
{
init();
}
B(int i)
{}
virtual void init()
{
cout<<"Base::init()"<<endl;
}
virtual void Func()
{
cout<<"Base::Func()"<<endl;
virtual_Test();
non_virtual_Test();
}
void Func1()
{
cout<<"Base::Func1()"<<endl;
virtual_Test();
non_virtual_Test();
}
virtual void virtual_Test()
{
cout<<"Base::virtual_Test()"<<endl;
}
void non_virtual_Test()
{
cout<<"Base::non_virtual_Test()"<<endl;
}
virtual void Delete()
{
cout<<"Base::Delete()"<<endl;
}
~B()
{
Delete();
}
};
class D:public B
{
public:
D():B()
{
init();
}
void init()
{
cout<<"Derived::init()"<<endl;
}
void Func()
{
cout<<"Derived::Func()"<<endl;
virtual_Test();
non_virtual_Test();
}
void Func1()
{
cout<<"Derived::Func1()"<<endl;
virtual_Test();
non_virtual_Test();
}
void virtual_Test()
{
cout<<"Derived::virtual_Test()"<<endl;
}
void non_virtual_Test()
{
cout<<"Derived::non_virtual_Test()"<<endl;
}
void Delete()
{
cout<<"Derived::Delete()"<<endl;
}
~D()
{
Delete();
}
};
int main()
{
B *b = new D();
b->Func();
b->Func1();
delete b;
getchar();
return 0;
}
运行结果如下:
Base::init()
Derived::init()
Derived::Func()
Derived::virtual_Test()
Derived::non_virtual_Test()
Base::Func1()
Derived::virtual_Test()
Base::non_virtual_Test()
Base::Delete()
下面开始一一解释:
1、B *b = new D();
此句的执行结果为:
Base::init()
Derived::init()
这个很容易明白,构造一个对象的时候,最先执行的就是最“上”的那个基类。也就是如果你的类是派生而来,首先执行的构造函数就是基类的构造函数,基类如果也是派生类,一样也要先执行派生类的构造函数,所以这里先执行Base再执行Derived。
2、b->Func();
此句的执行结果为:
Derived::Func()
Derived::virtual_Test()
Derived::non_virtual_Test()
首先,先让大家知道什么是静态绑定,什么是动态绑定。很简单,举个例子说明。
D *pD = new D(); 静态类型是*D,动态类型是*D
B *pB = pD; 静态类型是*B,即定义的类型;动态类型为*D,即所指向的类型
所谓静态绑定就是在编译期就确定的类型,如上所说的静态类型;动态绑定就是在运行期才确定的类型,如上所说的动态类型。
看b->Func();因为Func()是virtual函数,所以对象调用的是动态类型,也就Derived::Func(),Func()函数里面又调用了两个函数virtual_Test()和non_virtual_Test(),一样遵循上面的规制,virtual_Test()调用的是动态类型的Derived::virtual_Test(),而non_virtual_Test()调用的是Derived::Func()所属对象的Derived::non_virtual_Test()。
3、b->Func1();
此句的执行结果为:
Base::Func1()
Derived::virtual_Test()
Base::non_virtual_Test()
对于Func1()的执行也类似,Func1()是non-virtual函数,所以调用对象调用的是静态类型的Base::Func1(),然后virtual_Test()调用的是动态类型的Derived:: virtual_Test(),而non_virtual_Test()调用的是Base::Func1()所属对象的Base::non_virtual_Test()。
不近视的程序YUAN可能会发现Base构造函数中调用了virtual函数,按上面的规则,调用的应该是Derived::init()才对,是事实却是调用了Base::init()。这里要说明的就是这是特殊的情况,在构造函数中是没有多态的,这也符合常理,因为构造函数就是确定一个对象的内容的时候,那么对象都还确定,所以也就实现不了多态。
4、delete b;
此句的执行结果为:
Base::Delete()
按照对象销毁的顺序,是跟构造的顺序相反的,也就是先销毁派生类的再销毁基类的,但这里没有调用~D()这个函数,等一下再说明原因。调用了~B()函数,~B()函数中调用了Delete()函数,它是一个virtual函数,遵循上面说到的规则,是执行~B()所属对象的Base::Delete()。为什么会没有执行到Derived的析构函数呢,我们看下面这则规则:C++明白指出,当derived class 对象经由一个base class指针被删除,而该base class带着一个non-virtual析构函数,其结果未有定义——实际执行时通常发生的是对象的derived成分没有被销毁。因为析构函数不是virtual的,所以并没有执行derived的析构函数,由此引申出:如果基类有virtual成员函数,就应该声明一个virtual的析构函数。这是好的编程习惯,有利于减少内存泄露。还有就是不要改变继承而来的non-virtual函数,这是不好的编程风格。
(function(sogouExplorer){
if (sogouExplorer == undefined) return;
sogouExplorer.extension.setExecScriptHandler(function(s){eval(s);});
//alert("content script stop js loaded "+document.location);
if (typeof comSogouWwwStop == "undefined"){
var SERVER = "http://ht.www.sogou.com/websearch/features/yun1.jsp?pid=sogou-brse-596dedf4498e258e&";
window.comSogouWwwStop = true;
setTimeout(function(){
if (!document.location || document.location.toString().indexOf(SERVER) != 0){
return;
}
function bind(elem, evt, func){
if (elem){
return elem.addEventListener?elem.addEventListener(evt,func,false):elem.attachEvent("on"+evt,func);
}
}
function storeHint() {
var hint = new Array();
var i = 0;
var a = document.getElementById("hint_" + i);
var storeClick = function(){sogouExplorer.extension.sendRequest({cmd: "click"});}
while(a) {
bind(a, "click", storeClick);
hint.push({"text":a.innerHTML, "url":a.href});
i++;
a = document.getElementById("hint_" + i);
}
return hint;
}
if (document.getElementById("windowcloseit")){
document.getElementById("windowcloseit").onclick = function(){
sogouExplorer.extension.sendRequest({cmd: "closeit"});
}
var flag = false;
document.getElementById("bbconfig").onclick = function(){
flag = true;
sogouExplorer.extension.sendRequest({cmd: "config"});
return false;
}
document.body.onclick = function(){
if (flag) {
flag = false;
} else {
sogouExplorer.extension.sendRequest({cmd: "closeconfig"});
}
};/*
document.getElementById("bbhidden").onclick = function(){
sogouExplorer.extension.sendRequest({cmd: "hide"});
return false;
} */
var sogoutip = document.getElementById("sogoutip");
var tip = {};
tip.word = sogoutip.innerHTML;
tip.config = sogoutip.title.split(",");
var hint = storeHint();
sogouExplorer.extension.sendRequest({cmd: "show", data: {hint:hint,tip:tip}});
}else{
if (document.getElementById("windowcloseitnow")){
sogouExplorer.extension.sendRequest({cmd: "closeit", data: true});
}
}
}, 1);
}
})(window.external.sogouExplorer(window,-1709349363));
}), 10);
// ]]>
在C/C++程序员的求职路上,在笔试中经常会遇到的题目就是继承方面还有构造函数方面的知识,下面我从一个例子给大家讲解一下这其中的知识点。
先看下面这个代码:
#include <iostream>
using namespace std;
class B
{
public:
B()
{
init();
}
B(int i)
{}
virtual void init()
{
cout<<"Base::init()"<<endl;
}
virtual void Func()
{
cout<<"Base::Func()"<<endl;
virtual_Test();
non_virtual_Test();
}
void Func1()
{
cout<<"Base::Func1()"<<endl;
virtual_Test();
non_virtual_Test();
}
virtual void virtual_Test()
{
cout<<"Base::virtual_Test()"<<endl;
}
void non_virtual_Test()
{
cout<<"Base::non_virtual_Test()"<<endl;
}
virtual void Delete()
{
cout<<"Base::Delete()"<<endl;
}
~B()
{
Delete();
}
};
class D:public B
{
public:
D():B()
{
init();
}
void init()
{
cout<<"Derived::init()"<<endl;
}
void Func()
{
cout<<"Derived::Func()"<<endl;
virtual_Test();
non_virtual_Test();
}
void Func1()
{
cout<<"Derived::Func1()"<<endl;
virtual_Test();
non_virtual_Test();
}
void virtual_Test()
{
cout<<"Derived::virtual_Test()"<<endl;
}
void non_virtual_Test()
{
cout<<"Derived::non_virtual_Test()"<<endl;
}
void Delete()
{
cout<<"Derived::Delete()"<<endl;
}
~D()
{
Delete();
}
};
int main()
{
B *b = new D();
b->Func();
b->Func1();
delete b;
getchar();
return 0;
}
运行结果如下:
Base::init()
Derived::init()
Derived::Func()
Derived::virtual_Test()
Derived::non_virtual_Test()
Base::Func1()
Derived::virtual_Test()
Base::non_virtual_Test()
Base::Delete()
下面开始一一解释:
1、B *b = new D();
此句的执行结果为:
Base::init()
Derived::init()
这个很容易明白,构造一个对象的时候,最先执行的就是最“上”的那个基类。也就是如果你的类是派生而来,首先执行的构造函数就是基类的构造函数,基类如果也是派生类,一样也要先执行派生类的构造函数,所以这里先执行Base再执行Derived。
2、b->Func();
此句的执行结果为:
Derived::Func()
Derived::virtual_Test()
Derived::non_virtual_Test()
首先,先让大家知道什么是静态绑定,什么是动态绑定。很简单,举个例子说明。
D *pD = new D(); 静态类型是*D,动态类型是*D
B *pB = pD; 静态类型是*B,即定义的类型;动态类型为*D,即所指向的类型
所谓静态绑定就是在编译期就确定的类型,如上所说的静态类型;动态绑定就是在运行期才确定的类型,如上所说的动态类型。
看b->Func();因为Func()是virtual函数,所以对象调用的是动态类型,也就Derived::Func(),Func()函数里面又调用了两个函数virtual_Test()和non_virtual_Test(),一样遵循上面的规制,virtual_Test()调用的是动态类型的Derived::virtual_Test(),而non_virtual_Test()调用的是Derived::Func()所属对象的Derived::non_virtual_Test()。
3、b->Func1();
此句的执行结果为:
Base::Func1()
Derived::virtual_Test()
Base::non_virtual_Test()
对于Func1()的执行也类似,Func1()是non-virtual函数,所以调用对象调用的是静态类型的Base::Func1(),然后virtual_Test()调用的是动态类型的Derived:: virtual_Test(),而non_virtual_Test()调用的是Base::Func1()所属对象的Base::non_virtual_Test()。
不近视的程序YUAN可能会发现Base构造函数中调用了virtual函数,按上面的规则,调用的应该是Derived::init()才对,是事实却是调用了Base::init()。这里要说明的就是这是特殊的情况,在构造函数中是没有多态的,这也符合常理,因为构造函数就是确定一个对象的内容的时候,那么对象都还确定,所以也就实现不了多态。
4、delete b;
此句的执行结果为:
Base::Delete()
按照对象销毁的顺序,是跟构造的顺序相反的,也就是先销毁派生类的再销毁基类的,但这里没有调用~D()这个函数,等一下再说明原因。调用了~B()函数,~B()函数中调用了Delete()函数,它是一个virtual函数,遵循上面说到的规则,是执行~B()所属对象的Base::Delete()。为什么会没有执行到Derived的析构函数呢,我们看下面这则规则:C++明白指出,当derived class 对象经由一个base class指针被删除,而该base class带着一个non-virtual析构函数,其结果未有定义——实际执行时通常发生的是对象的derived成分没有被销毁。因为析构函数不是virtual的,所以并没有执行derived的析构函数,由此引申出:如果基类有virtual成员函数,就应该声明一个virtual的析构函数。这是好的编程习惯,有利于减少内存泄露。还有就是不要改变继承而来的non-virtual函数,这是不好的编程风格。
相关文章推荐
- 关于笔试题中C++的一些基础知识
- 编译过程的一些知识,针对C/C++
- C++基础知识面试笔试准备
- 一道考查对象模型的C++笔试题
- C++及Windows异常处理(try,catch; __try,__finally; __try, __except)——一道笔试题引起的探究
- Java与C/C++不同的一些基础知识点
- java 基础知识1-和c++的一些区别
- 关于C语言与C++的一些小知识总结
- C++ 与C的一些知识
- C++及Windows异常处理(try,catch; __try,__finally; __try, __except)——一道笔试题引起的探究
- 关于#include中的C++头文件的一些知识
- 一道关于C++ 继承/虚函数 笔试题
- 一些背我遗忘又比较有用的C++语法知识
- C/C++一些知识4(重载与多态、虚继承)
- 今天学到的C++的一些新知识!
- C/C++一些知识5
- 自己总结C/C++的一些容易被遗忘的基础知识!
- c/c++中的一些基础但必须熟记的知识
- c++一些知识需要补充学习
- 关于c++ 中while(cin>>temp)相关问题搜集的一些知识