首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

三个题目,给大家参考。该如何解决

2012-02-21 
三个题目,给大家参考。这三个题是我前些时候找工作时遇到的最难最有代表性的三个题目。拿出来给正在找工作的

三个题目,给大家参考。

这三个题是我前些时候找工作时遇到的最难最有代表性的三个题目。
拿出来给正在找工作的朋友参考下,或者学习,或者增强信心,都是善事一件。

1.

构造函数中可不可以抛出异常?析构函数呢?

2. 这个题我实在记不清楚到底是怎么出的了,我自己参补成一个题,大家明白什么意思就行了。

C/C++ code
class B{public:     void f(int) const    {    }     void f(double) const    {    }};class D: public B{public:    void f(void*) const    {    }};D d;d.f(0); //调用那个函数?d.f(1); //调用那个函数?d.f(0.1); //调用那个函数?


3.

STL中的traits是什么?请举例实现。



注:本人在脚本语言区另有一帖,对Perl、Python或者Tcl熟悉的朋友可以去看看:
出几个小题目,活跃下气氛。




[解决办法]
楼主好人,收藏学习
[解决办法]
第二题都父类B的两个重载函数被子类D隐藏了,所以不可能被调用到,
不过我在mingw下下面两个调用都出错
d.f(1); //调用那个函数?
d.f(0.1); //调用那个函数?
[解决办法]
呵呵,试了才知道,原来编译都过不了,本以为没问题的。看来基础还不扎实
[解决办法]
如果把void*放到基类里,double放到子类里就可以运行。为什么呢?void*有什么特别的吗?等待高人
[解决办法]
lz是好人啊
可惜晚拉一点,你要是早放出来多好啊;
我今天上午就考拉第二题
研究下
[解决办法]
up

[解决办法]
up2
[解决办法]
up3
[解决办法]
>_<
[解决办法]
在C++类里面,存在两个概念,一个是重载,一个是覆盖。
重载只是在类的内部存在,不会传导到父类和子类中间。即便是一个函数声明为virtual,也是这样。
如果一个类,存在和父类相同的函数,那么,这个类将会覆盖其父类的方法,除非你在调用的时候,强制转换为父类类型,否则试图对子类和父类做类似重载的调用是不能成功的。
例如下面的例子

class B
{
public:
void f(int i) const
{
printf("B::f(int):%d\n",i);
}
virtual void f(double d) const
{
printf("B::f(double):%f\n",d);
}
};

class D: public B
{
public:
void f(void* p) const
{
printf("B::f(void*):%x\n",p);
}
void f(int i) const{
printf("D::f(int):%d\n",i);
}
};



int main(int argc, char* argv[])
{
D d;
((B*)&d)->f(0); //强制调用,否则父类的f(int)对子类不可见
d.f(1);
((B*)&d)->f(1); //
((B*)&d)->f(0.1); //
d.f(0.1);//这里报出警告test.cpp(40) : warning C4244: 'argument' : conversion from 'const double' to 'int', possible loss of data,说明系统不能识别具有virual的隔代重载。
d.f(NULL);
printf("Hello World!\n");
getchar();
return 0;
}

那么,对于纯虚函数呢,实际情况也是一样的。例如
class Y:public X{
public:
virtual void f(int n){
printf("Y::f(int):%d\n",n);
}
virtual void f(double d){
printf("Y::f(double):%f\n",d);
}
};

class Z:public Y{
public:
virtual void f(int n){
printf("Z:f(int):%d\n",n);
}
};

Z z;
z.f(1);
z.f(0.1); //警告了
结果是
Z:f(int):1
Z:f(int):0

[解决办法]
我对异常一无所知,从来不用。

第二题留给编译器,觉得有些无聊啊,
不过我想猜猜,
第一个调用派生类的,
第二个编译不过。
第三个是基类的。

第三题对我来说太简单了。

发帖留念。。。 。。。敢于面对自己的无知和错误吧~

[解决办法]
我果然无知加错误。。。 。。。怎么都覆盖了???


[解决办法]
1. 我跟草哥一样,从来没用过一场,除了用com的时候照着写了下 - -

2. 感觉编译不过,除非改成

d.B::f(1);
d.B::f(0.1); 

3. 萃取器??- -! C++ stl 采鸟飞过


[解决办法]
第二题,一个void f(void*) const把基类的两个全给隐藏了.
[解决办法]
STL中的traits,我的理解就是具有统一接口,不同实现的部分,也就是特化、偏特化派上用场的地方。
比如string的char_traits, iterator的traits等等。
[解决办法]
void可以匹配所有的类型吧
[解决办法]
bcb6.0调用d.f(0.1); 时给出的编译错误Incompatible type conversion

而调用d.f(1);给出的编译错误是Can't convert "int" to "void*" and Type missmatch in parameter1(wanted "void*" got "int")

这里的为什么还不一样啊,我觉得该一样啊
[解决办法]
是隐藏,不是覆盖
[解决办法]
我和楼主想得不一样,在C#中特意用关键字new来阐明是不是覆盖关系,我觉得这里是C++晦涩的地方,写代码的时候要尽量避免,而且调试的时候很容易调试出来。
异常不懂,据说在C++里面异常太诡异了,往往用了效果更加复杂,所以我基本不用。
第三个是技巧,写模板代码一定用到,可以看C++ templates那本书关于traints和policy的那一节。MCD也有区分。

[解决办法]
构造函数:
构造函数中如果抛出异常,可见析构函数并没有被调用,这样子的话就产生了内存泄漏,所以如果要在构造函数抛出异常之前,应该先把已经成功分配的资源释放掉.
在C++中,经典的解决方案是使用STL的标准类auto_ptr,并且不要做过多的事情,只是能对成员变量的做初始化工作就好了。真的需要做其他复杂的初始化操作,完全可以提供一个Init或Start函数.

析构函数:
C++ 并 没有禁止析构函数引发异常,但 是 C++ 十 分不推荐这一做法。
[解决办法]
to:healer_kx and Chiyer:
你们不怎么用异常?
请问你们是搞工作的,我觉得异常在c++中很重要啊.
[解决办法]
to:healer_kx and Chiyer: 
你们不怎么用异常? 
请问你们是搞工作的,我觉得异常在c++中很重要啊.[color=#FF6600][/color]
[解决办法]
目前我写的代码要在gcc3,4,vc7上都编译啊,而且要求逻辑要一致啊。

那c语言工作者怎么办啊?

[解决办法]
大家都搞不太明白,说明语言本身有问题。
[解决办法]
以为2题仅仅都是子类隐藏了父类的函数,看下面的回复却发现貌似编译都过不去啊。。。
[解决办法]
有功夫我会好好看看异常的,要不对不起大家给我的可用分~~~~

[解决办法]
我也发了两个小问题。
http://topic.csdn.net/u/20071020/23/bb6d81c1-da9f-4bfc-a679-13ba66399c5a.html
[解决办法]
好贴子,

使劲顶
[解决办法]
MARK!
[解决办法]
飞过
[解决办法]
1.NO EXCEPTION FOR CONSTRUCTOR AND DESTRUCTOR
2.http://topic.csdn.net/u/20070812/11/ec535999-b969-44d5-aba8-d3f07b110ce8.html
以前类似的讨论,就是大家不加注意而已,很不错的问题,我后来查了primer,里面有提及,
这样情况需要明确加上名字空间,虽然重载原型是不同的~~~
3.
template <class MAY_BE_A_ITERATOR> class iterator_traits
{
typedef typename MAY_BE_A_ITERATOR::value_type value_type;
// if MAY_BE_A_ITERATOR is a STL-like iterator,it must have a nested type
.....
}
template <class U> class iterator_traits<U*>
{
typedef U value_type;
// specifization for pointer type ,because a pointer is iterator alike


...
}
traits思想博大精深,类似于Imperfect C++里面提及的垫片技术
简单来说就是让相似但不同的东西有相似的接口
[解决办法]
为什么第二个会编译不过?
是子类隐藏了父类的函数?
还是由于参数二义性造成的?

楼上不确定的各位可以把子类中的声明
void f(void*) const
改成
void f(char) const
再去看看结果...

然后再想想 Effective C++ (2nd Edition)中
Item 25: Avoid overloading on a pointer and a numerical type
相关内容...

[解决办法]
对于第二个问题:C/C++ code
class B
{
public:
void f(int) const
{
}
void f(double) const
{
}
};

class D: public B
{
public:
void f(void*) const
{
}
};

D d;
d.f(0); //调用那个函数?
d.f(1); //调用那个函数?
d.f(0.1); //调用那个函数?
调用的都是派生类D内的函数“void f(void*) const”,具体分析如下:C++中有三个概念:重载、覆盖、隐藏,本题中主要考察的是“隐藏“。
所谓隐藏是指:派生类的函数屏蔽了与其同名的基类函数。隐藏一般分为两种情况:1:基类与派生类函数名相同,参数不同,基类函数前无论有无关键字
“virtual”,如果是公有继承的话,继承到派生类的基类函数将被隐藏(注意与重载区别)。2:基类与派生类函数名相同,参数相同,但基类函数前无关键字“virtual”,同样,如果是公有继承的话,继承到派生类的基类函数被隐藏(注意与覆盖的区别)。
[解决办法]
Sorry, I am wrong....
[解决办法]
上面有点错误,如果是私有继承或受保护继承,就不会和派生类中的成员函数产生冲突了,但此时应注意:参数的类型。
[解决办法]
对于第一个问题:构造函数是否可以抛出异常:可以分为两种情况。1:如果捕捉异常处理信息的catch也在此构造函数内,则是可以的。如程序:
#include<iostream>
using namespace std;
class B
{
public:
B(int a, int b, int c)
{
aa=a;
bb=b;
cc=c;
try
{
if(aa+bb<=cc || aa+cc<=bb || bb+cc<=aa)
throw aa;
}
  
catch(int)
{
cout<<aa<<" "<<bb<<" "<<cc<<" "<<"is not a triangle"<<endl;
}
}
private:
int aa;
int bb;
int cc;
};

int main(void)
{
B b(1, 2, 1);
return 0;
}

2:如果捕捉异常处理信息的catch不在此构造函数内,则是不可以的。因为类的构造函是由系统在创建对象时自动调用的,不受任何其他函数的调用。
如果构造函数中无catch。那么,该程序将会异常中止。
[解决办法]
关于第三点:不好意思,我也不知道。哈哈。
只好 up 了。
[解决办法]
MARK
[解决办法]
析构函数应该不抛出异常。
构造函数可抛出异常,但要保证撤销已构造的元素。
[解决办法]


楼主应该是刚刚升的星星吧,前几天还五个三角呢,呵呵.
散专家分,涨知识又活跃气氛

楼主好人.
[解决办法]
从lz的升星事件中看出了csdn技术的变化:已经将很多动态网页静态化了,以提高响应速度。看来csdn论坛的规模应该有上百万级别了吧!
见帖子
http://topic.csdn.net/u/20071014/18/e1de3e14-5161-4f88-b9a9-aa94dd44bdb8.html
注意在此贴中的iambic还是五裤衩级别的人物。
[解决办法]
如果在构造函数中抛出异常。。。应该自定个匹配的NEW函数,以供异常后调用。
析构抛出异常??有点玄啊。。。
[解决办法]
up
[解决办法]
不太明白!
[解决办法]
mark
[解决办法]
高深,学习
[解决办法]
感谢楼主. 你的前两个问题让我想起<Exceptional C++>一书. 问题1在此书的Item8和Item16, 问题2在Item34中,都有详尽的解释. 看来此书也是应付面试之法宝.


[解决办法]
up
[解决办法]
mark下。
[解决办法]
好贴字,不住的顶
[解决办法]
路过学习了。 

[解决办法]
还是感觉垫片包含triats,……不知道为什么说垫片是traits的子集,老实说这些东西哪里有严格的定义?
[解决办法]
前几天刚看过这几题,怎么又看到了。
路过。

楼上的分析啦。

3、 我无知
[解决办法]
感谢楼主

[解决办法]
原来如此我理解错了,反正我感觉imperfect里面说的shim似乎可以包括了traits是一种广义的设计
反正无所谓,每个人起的名字不同而已。
<martix>:重要的不是名字,而是名字后面隐藏的东西(似乎,是在trainman那里的一段)
[解决办法]
D d;
d.f(0); //调用那个函数?
d.B::f(1); //调用那个函数?
d.B::f(0.1); //调用那个函数?
[解决办法]
好贴,学习一下。
[解决办法]
(1) 构造函数好像不可以抛出异常 但别让异常逃离析构函数
(2) D类中的
void f(void*) const
会覆盖B类中的
void f(int) const
{
}
void f(double) const
{
}
所以基类中的non-virtual 坚决不要重定义
(3) traits 好像是用来表现类的信息(本人用的少)

这些问题在 effecitve c++中都有提起
大家去看看吧


[解决办法]
学习啊,LZ 好人也。
[解决办法]
mark
[解决办法]
最近看stl,里面的很多地方用了traits,大部分应用我觉得是不同类型提供一个统一的接口.

比如迭代器的实现里的traits类的一个特化实现指针和迭代器的统一,也可以用函数重载实现.

不知说的对不.?
[解决办法]
学习了长知识了
[解决办法]
1、不是很清楚,构造函数中抛出时对象还未完全被构造,如果要抛出,就要明确哪些部分已经被构造并做相应的清理工作。这对于初始化列表来说更是麻烦。析构函数中不应该抛出异常。C++ primer中异常部分有讲,长久不用忘记了-。-
2、同意HULIHONG说的,基类函数都被隐藏了。
3、类型萃取器,好像还能萃取enum和static method,用于在模板中统一处理不同类型但有相同行为的类型。菜鸟理解……

热点排行