×

Loading...
Ad by
  • 技多不压身,工到自然成:安省技工证书特训班,点击咨询报名!
Ad by
  • 技多不压身,工到自然成:安省技工证书特训班,点击咨询报名!

典型C++题一道,请写出输出结果。

class A
{
public:
	A() : m_a(0)
	{ 
		printf("A::A"); 
	}
	virtual ~A()
	{ 
		printf("A::~A m_a=%d", m_a); 
		foo();
	}

	virtual void foo()
	{
		printf("A::foo");
	}

	int m_a;
};

class B : public A
{
public:
	B() : m_b(0)
	{
		printf("B::B"); 
	}
	virtual ~B()
	{ 
		printf("B::~B m_b=%d", m_b); 
		foo();
	}

	virtual void foo()
	{
		printf("B::foo");
		throw 1;
	}

	int m_b;
};

int main(int argc, char* argv[])
{
	printf("Test 1:");
	try
	{
		B b;
	}
	catch(int)
	{
	}

	printf("Test 2:");
	A a;
	B *pB1 = (B*)&a;
	B *pB2 = static_cast(&a);
	B *pB3 = dynamic_cast(&a);
	B *pB4 = reinterpret_cast(&a);
	printf("&a=0x%x, pB1=0x%x, pB1=0x%x, pB1=0x%x, pB1=0x%x", &a, pB1, pB2, pB3, pB4);
	
	printf("Test 3:");
	pB1->foo();
	pB1->m_b = 1;
	printf("m_a=%d, m_b=%d", pB1->m_a, pB1->m_b);

	return 0;
}
Report

Replies, comments and Discussions:

  • 工作学习 / 科技领域杂谈 / 典型C++题一道,请写出输出结果。
    class A
    {
    public:
    	A() : m_a(0)
    	{ 
    		printf("A::A"); 
    	}
    	virtual ~A()
    	{ 
    		printf("A::~A m_a=%d", m_a); 
    		foo();
    	}
    
    	virtual void foo()
    	{
    		printf("A::foo");
    	}
    
    	int m_a;
    };
    
    class B : public A
    {
    public:
    	B() : m_b(0)
    	{
    		printf("B::B"); 
    	}
    	virtual ~B()
    	{ 
    		printf("B::~B m_b=%d", m_b); 
    		foo();
    	}
    
    	virtual void foo()
    	{
    		printf("B::foo");
    		throw 1;
    	}
    
    	int m_b;
    };
    
    int main(int argc, char* argv[])
    {
    	printf("Test 1:");
    	try
    	{
    		B b;
    	}
    	catch(int)
    	{
    	}
    
    	printf("Test 2:");
    	A a;
    	B *pB1 = (B*)&a;
    	B *pB2 = static_cast(&a);
    	B *pB3 = dynamic_cast(&a);
    	B *pB4 = reinterpret_cast(&a);
    	printf("&a=0x%x, pB1=0x%x, pB1=0x%x, pB1=0x%x, pB1=0x%x", &a, pB1, pB2, pB3, pB4);
    	
    	printf("Test 3:");
    	pB1->foo();
    	pB1->m_b = 1;
    	printf("m_a=%d, m_b=%d", pB1->m_a, pB1->m_b);
    
    	return 0;
    }
    
    • 有两个小小的bug:C++ cast漏了类型,打印指针的时候字符串里变量名。打印加换行好看点。把父类指针cast到子类指针得非常小心。最好是不需要cast,而是依赖polymorphism。在c-tor和d-tor里调用virtual function也是搞笑。当然最有破坏力的是pB1->m_b = 1
      class A
      {
      public:
      A() : m_a(0)
      {
      printf("A::A\r\n");
      }
      virtual ~A()
      {
      printf("A::~A m_a=%d\r\n", m_a);
      foo();
      }

      virtual void foo()
      {
      printf("A::foo\r\n");
      }

      int m_a;
      };

      class B : public A
      {
      public:
      B() : m_b(0)
      {
      printf("B::B\r\n");
      }
      virtual ~B()
      {
      printf("B::~B m_b=%d\r\n", m_b);
      foo();
      }

      virtual void foo()
      {
      printf("B::foo\r\n");
      throw 1;
      }

      int m_b;
      };

      int _tmain(int argc, _TCHAR* argv[])
      {
      printf("Test 1:\r\n");
      try
      {
      B b;
      }
      catch(int)
      {
      }

      printf("Test 2:\r\n");
      A a;
      B *pB1 = (B*)&a;
      B *pB2 = static_cast<B*>(&a);
      B *pB3 = dynamic_cast<B*>(&a);
      B *pB4 = reinterpret_cast<B*>(&a);
      printf("&a=0x%x, pB1=0x%x, pB2=0x%x, pB3=0x%x, pB4=0x%x\r\n", &a, pB1, pB2, pB3, pB4);

      printf("Test 3:\r\n");
      pB1->foo();
      pB1->m_b = 1;
      printf("m_a=%d, m_b=%d\r\n", pB1->m_a, pB1->m_b);

      return 0;
      }
    • 端个小板凳,带上笔记本,等高人评点。。。
      • 我随便说说
        这是一道比较有趣的题目。主要考察方向大概有以下几点:
        1,关于从析构函数里面抛出异常,这是允许的。但是不允许从构造函数抛。
        2,关于DOWN CAST,这几种都是可以的。dynamic_cast会在你CALL了一个A中不存在的方法的时候抛出std::bad_cast异常。但是这里没有CALL,所以没有。
        3,执行->foo的时候,因为A当中也有这个方法,是正常执行。
        4,给mB给值的时候,超界了, sizeof(B)和sizeof(A)在这里是不同的。所以当你退出程序的时候,出错。STACK崩溃。
    • Q1:What really happens when you call virtual function and throw exception in dtors? Q2:What's the difference between those castings? Q3: What exactly will "pB1->m_b = 1;" do here? Thanks wangqingshui for formatting and correcting variable names.
      • A1: calling virtual function in dtor I believe the function is considered non-virtual because the object of the derived class part has been destructed already.
        • Yes, if virtual function was called directly from ctor/dtor, it is not considered as virtual; however if it is called indirectly (e.g. through another non-virtual function), it will be considered as a virtual function call and vtable will be used.
      • A1: Throwing exception from dtor or from functions called in dtor may cause 2 parallel unhandled exception and abort the application.
        • The try/catch will catch the C++ exception, and the exception didn't even stop stack unwinding.
      • Q3: it is kind of similar to the situation that someone intrusively peed in his neighbour's yard, possibly burnt a precious flower, or maybe peed into empty area without any actual damage.
        • Normally it corrupts stack depending how far it goes. With VC8, it runs without problem with release build and error of stack corruption in debug build.
      • 钻牛角尖的时间用在任何地方得到的回报都要比钻牛角尖高。
        • 拿一堆code,问人家结果,比钻牛角尖更浪费时间。