今天面试碰到的一个以前没有想过的问题(顺便给一点分出去)

今天面试碰到的一个以前没有想过的问题(顺便给一点分出去)

 

该题写的是考查应聘者对于C++中的存取权限的理解,但经我稍微的分析,觉得不完全如是,现把它公开出来,希望各位能够畅所欲言,发表自己的看法。

有类A,它被定义在a.h中,Aprivate成员i,如下:

class A {

private:

   int i;

             // ...

};

A的实现在a.cpp中(具体细节略)。在另外一个main.cpp中,我们使用了A,当然,我们知道直接访问A::i是不可能的。现在问题开始了,我们先把a.cpp编译成a.obj,然后修改a.h,把i改为public,然后我们再编译main.cpp,得到main.obj,然后把main.obja.obj放到一起去链接,问:这样做是否可以成功

我觉得这个问题很是有意思,因为根据以前接受过的正统熏陶,a.h被修改后,项目中的a.cpp肯定是要重新编译的,但这个题目没有这样做。所以让我很是费解了一番,自己胡乱写了一点上去,天知道是否正确与否:(

Frank001Frank回复于 2003-02-27 18:35:01 得分 5

我个人认为这样链接不能成功。

  因为在编译a.cpp的时候, a.cpp里肯定有a的声明,要么直接写进去,要么用#include"a.h"包含进去,预处理的时候展开,然后编译,所以a.obj里的iprivate的,这时改了a.ha.obj是不起作用的,而main.cpp里展开后ipublic的,所以链接是不会成功的。

HaiFen(小石头)回复于 2003-02-27 19:36:49 得分 10

不一定,有的编译器链接失败,因为它们把成员的访问属性也编码到函数名上了,改了访问属性后编码后的函数名也不一样,而且,有的编译器会把属于不同访问属性的成员的位置进行一定的调整,合并等等,运行后就会出错。

12 chinajiji(菜鸟叽叽)回复于 2003-02-27 20:22:23 得分 80

暂不考"虑继承,多重继承,虚拟多重继承,有虚拟函数"的情况下:

非静态成员可以link成功,静态成员与成员函数不能link成功.

因为静态成员与成员函数的名字在加入obj文件中的符号表时,一般会添加访问控制标识,而非静态成员在class中用偏移量表示,在生成对象时才分配实际空间,访问时通过对象的地址加上成员在class中的offset得到它的实际地址.也就是说在a.obj文件中没有非静态成员的空间分配,当然也没有相关的访问控制标识写入a.obj的符号表中,所以可以link成功.

24 ybco()回复于 2003-02-28 02:14:14 得分 5

看来各位对C++Preprocessor的作用太不了解!!!

在编译a.obj时,a.h就已被Preprocessor拖进来,此后,任你怎么改a.h,都没用,a.obj “看不见!!,除非重新编译。

所以,正确答案是:不行。

25 ckacka/*小红帽*/ckacka();回复于 2003-02-28 02:58:57 得分 10

一般情况下都是可以的!

如下:

 

  //main.cpp

  #include "class.h"

  #include <iostream>

  using namespace std;

 

  int main(void)

  {

  CA* a = new CA;

  a->i = 1;

 

  cout << a->i << endl;

 

  system("pause");

  return 0;

  }

 

 

  //class.cpp

  #include "class.h"

 

 

  //class.h

  class CA

  {

  public:

  int i;

  };

27 ybco()回复于 2003-02-28 04:22:58 得分 0

莫忘了你用的是开发公具来编译,所以能行。因为那工具会自动发现 a.h 的修改时间比a.obj新,它马上会重新编译 a.obj 当然没问题了。这也实际开发中的情况。

  原问题不是这样问的。

28 saucer(思归)回复于 2003-02-28 05:35:00 得分 15

  1. a.h:

  class A {

  private:

    int i;

  public:

    A (int x):i(x){}

    void dummy();

  };

 

  2. a.cpp:

  #include "a.h"

 

  void A::dummy()

  {

  int xxx;

  }

 

  3. main.cpp:

  #include "a.h"

  #include <iostream>

  using namespace std;

 

  void main()

  {

  A a(123);

  cout << a.i << endl;

  cout << *((int*)&a) << endl;  

  }  

  c:/>cl /c a.cpp

  .......modify "a.h" to have a public i

  c:/>cl /c main.cpp

  c:/>link main.obj a.obj  

  the last two steps can be combined:

  c:/>cl main.cpp a.obj

  and it runs:    

  c:/>main

  123

  123

  here is a thread which discusses a similar problem:

34 Bandry(菜鸟-舍我其谁)回复于 2003-02-28 08:53:12 得分 10

应该是可以的,以前我的老总是微软ms操作系统开发部的一个小头目,他就说过publicprivate这些东西只是对我们程序员的限制,根本就不能保证数据的安全性,publicprivate数据编译以后在内存中没有区别,所以我觉得这两个obj肯定能链接成功,而且i也能被访问。

35 Tommy()回复于 2003-02-28 09:13:04 得分 10

同意saucerearthharp(骄傲的石头chinajiji(菜鸟叽叽)等的观点。

对于类的成员变量,一般都只是通过在类中的偏移值进行访问,并不会在符号表中生成一个符号项,也就不存在符号名称不同的问题了。只有静态成员变量才会在符号表中有入口。

只要编译器在publicprivate情况下不对变量在类中的位置进行调整就不会出错。C++一般只是保证在正常情况下不会误用,你问题可以用一些手段去绕过类型检查系统的。

  不单是变量的访问权限修改后可以顺利连接,就算类的结构发生改变也是可以通过C++的编译的。有时我们使用了一个第三方提供的LIB文件,但是却用了一个错误版本的.H文件,程序可以顺利编译、连接,但是运行时却会失败,就是因为LIB文件和.H文件中的类的定义不同,但是C++却不能发现,但是访问的内容完全是错误的啦

54 fly_jason()回复于 2003-02-28 13:28:44 得分 0

我用VC6.0没有编译通过

  class A

  {

  //private:

  public:

  void Output();

  };

 

  void A::Output()

  {

  cout << "A::Output" << endl;

  }

  main()

  {

  A a;

  a.Output();

  }

  unresolved external symbol "public: void __thiscall A:

  :Output(void)" (?Output@A@@QAEXXZ)

  a.exe : fatal error LNK1120: 1 unresolved externalsTop

57 fengye()回复于 2003-02-28 16:59:34 得分 0

link是否成功估计是和编译器name decorate方法有关我试了这样的例子

  a.h:

  #ifndef A_H_INCLUDED

  #define A_H_INCLUDED

 

  #ifndef ACCESS

  #define ACCESS private

  #endif

 

  class A {

  ACCESS:

  void fun();

  static void sfun();

  };

 

  #endif

 

  a.cpp:

 

  #include "a.h"

  #include <iostream>

 

  void A::fun()

  {

  std::cout << "fun" << std::endl;

  }

 

  void A::sfun()

  {

  std::cout << "static fun" << std::endl;

  }

 

  main.cpp:

 

  #define ACCESS public

  #include "a.h"

 

  int main()

  {

  A a;

  a.fun();

  A::sfun();

  }

 

  结果, bcc 5.5.1gcc 3.2.2(mingw)可以, vc 7.1不可以(两个函数都不可以)

  估计这也是implementation define的特性哪位有空到标准里去找找看 :)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值