C++-下面一段C++关于类继承的代码为什么会编译通过
请看下面一段关于C++类继承的代码:
#include <iostream>
using namespace std;
class A{
public:
A(int a,int b)
:lval(a),rval(b)
{
}
virtual int eval() = 0;
int getLVal()
{
return lval;
}
int getRVal()
{
return rval;
}
private:
int lval,rval;
};
class B:public A{
public:
virtual int eval()
{
return getLVal() + getRVal();
}
};
class C:public A{
public:
virtual int eval()
{
return getLVal() - getRVal();
}
};
int main()
{
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
首先,在子类B对象在构造时会先构造基类A对象,如果子类没有指定基类的构造函数,会调用其默认的无参构造函数,但A类中未定义该函数。
其次,代码编译时应该是可以通过的,只是在链接阶段,链接器找不到A类默认构造函数符号的定义地址。所以如果没有定义B类型的变量,连接器当然不会去链接A构造函数的符号,也就不会报错了。
我翻了一下C++的书,貌似找到了一点信息。
上述代码中的错误直到一个使用点上,才被标记出来,这在C++中叫做迟缓型错误检测(Lazy error detection)。这种策略确实是正在使用的策略。我们的代码可能充满了各种未触发的语言错误,而且在以后可能被随时激活。在迟缓型错误检测的策略下,成功编译并不能确保它没有语义错误,只能保证层序没有违反语言的语义规则。
迟缓型错误检测策略可以提高程序性能。它常常被应用在昂贵资源的初始化和分配上,直到真正需要这些资源时才分配或者初始化。如果这些资源永远也没有被真正用到,则我们就可以节省下不必要的运行开销。如果需要这些资源,但不是一次需要全部资源,则我们可以分散程序的初始化开销。
我们必须小心谨慎的测试我们的代码,以便找到并解决潜在的错误。在组合两个或多个大型组件时,少量潜在的错误是可以介绍的,但是在单个组件中,往往是不可接受的。
这个是这样的:
1. 当你的派生类中没有显示定义构造函数时,编译器会自动给你生成一个(四种情况,你懂得),其中会调用基类的默认构造函数。
2. 如果你的基类定义了自己的构造函数,那么就会覆盖掉默认构造函数,子类此时必须构造自己的构造函数并显示的调用基类构造函数。
3. 如果你不定义子类的对象,编译不会有错,因为根本不会涉及到对这些构造函数的调用;当你定义子类对象时,编译器就会提示找不到基类的默认构造函数,因为基类的默认构造函数已经被基类中自己定义的构造函数给覆盖掉了。
虽然不清楚编译器为什么这么设置。但是反过来这么一想,
你都不准备使用这个派生类对象,做为编译器的我为什么还花一笔开销给你去检测这种错误呢?这不是浪费么?
而当你使用了这个派生类对象,做为编译器的我自然不会放过这个错误,把你程序当中出现的问题给检测出来。
一个是不论你用不用我都检测?一个是你使用我才检测?
但是共同之处是都不会放过这个错误!
纯属个人理解,期待更专业的解答!
编译时,只要程序在执行的入口到return都可以在词义、语义上讲得通即可生成目标文件
而派生类与父类构造方法中出现的问题是在执行了有效的实例化语句之后才会出现的。
单独编译派生类的定义部分,没有语法错误,编译自然不需要报错;
单独编译空白的入口函数,也没有语法错误,也不需要报错;
当添加了实例化派生类的语句,编译器发现原来的声明中没有对构造的说明,与父类不配套,自然就报错喽
祝好,
斑驳敬上
应该是被编译器给优化掉了。
我试着编译了main函数中为空的情况,生成的汇编代码(VS2008,Debug)中没有任何关于类A或类B的信息。
进一步验证,
我试着添加了如下代码:
A() {} // 在类中声明默认构造函数,这样才能通过编译
int main()
{
B bObj;
}
注意,代码中没有定义类C的对象,重新编译,生成的汇编代码中有类A类B的信息,但没有类C的信息。
所以我在想,是不是编译器没有找到一个该类的对象的定义,为了减少生成代码的长度,索性就不生成相关类的汇编代码了。(这个可以从前面的分析得到验证)
没有使用就没有去申请内存空间,代码没有语义上的错误就可以编译通过啊。代码段是放在内存的.text段。类B的代码也是放在这。没有语义错误,不会报错。但是当你定义了一个B,编译就知道要去申请内存空间,调用构造函数,当没有合适的构造函数就会报错。只要你不使用,只要符合语义就行了,谁知道你是不是写着完的,或者你还没写完,你留着以后扩展用的,没必要检查那么严格,那就留在代码段吧,不碍事。当你要用时编译器才会去检查是否可用。
个人观点。欢迎指正!