Friday, February 25, 2011

回来后又接到一个电话

是Bloomberg的电话面试,问一些C++的问题。不是很难,在《Accelerated C++》里面都有谈到过。但毕竟我是看书学习,没有什么hands-on exercise的经验,所以答得磕磕绊绊。最后那个面试者就说你不用过来面试了,因为Bloomberg expects quick and correct answers.

:-(

一天fail掉两个面试,看来还得加强基本功。没事要少看看围棋网站了。


主要跌跤的地方:

1. When is the copy constructor necessary?
我回答的是initialization的时候需要(这个对),还有就是convert的时候需要(这是错的,convert需要一个constructor,但不是copy constructor)。正确答案是:
---
11.3.6 The rule of three

Classes that manage resources such as memory require close attention to copy control. In general, the default operations will not suffice for such classes. Failure to control every copy can confuse users of the class and often will lead to run-time errors.

Consider our Vec class, but pretend that we did not define the copy constructor, assignment operator, or destructor. As we saw in §11.3.1/195, at best we will surprise our users. Users of Vec will almost surely expect that once they've copied one Vec into another, the two objects will be distinct. They will expect that operations on one Vec will not have any effect on the data held by the other.

Even worse, though, is that if we do not define a destructor, then the default destructor will be used. That destructor will destroy the pointer, but destroying a pointer does not free the space to which it points. The result will be a memory leak: The space consumed by Vecs will never be reclaimed.

If we fix the leak by providing a destructor, but we do not also add the copy constructor and assignment operator, then we set things up so that a crash is likely. In such a flawed implementation, it would be possible for two Vecs to share the same underlying storage, as we illustrated in the first diagram in §11.3.1/196. When one of those objects is destroyed, the destructor will destroy that shared storage. Any subsequent reference through the undestroyed copy will lead to disaster.

Classes that allocate resources in their constructors require that every copy deal correctly with those resources. Such classes almost surely need a destructor to free the resources. If the class needs a destructor, it almost surely needs a copy constructor, as well as an assignment operator. Copying or assigning objects of classes that allocate resources usually allocates those resources in the same way that creating an object from scratch does. To control every copy of objects of class T, you need

    T::T(); one or more constructors, perhaps with arguments
    T::~T() the destructor
    T::T(const T&) the copy constructor
    T::operator=(const T&) the assignment operator

Once we have defined these operations, the compiler will invoke them whenever an object of our type is created, copied, assigned, or destroyed. Remember that objects may be created, copied, or destroyed implicitly. Whether implicitly or explicitly, the compiler will invoke the appropriate operation.

Because the copy constructor, destructor, and assignment operator are so tightly coupled, the relationship among them has become known as the rule of three: If your class needs a destructor, it probably needs a copy constructor and an assignment operator too.
---
From Andrew Koenig's 《Accelerated C++》

2. Can a copy constructor be virtual?
正确答案:No. (原因尚不确切)Only destructors can be virtual.

3. When do we need a virtual destructor?
正确答案是:
---
Dynamic binding refers to the ability to select at run time which function to run based on the actual type of the object on which the function is called. Dynamic binding is in effect for calls to virtual functions made through a pointer or a reference. The fact that a function is virtual is inherited, and need not be repeated in the derived classes.

Derived classes are not required to redefine their virtual functions. If a class does not redefine a virtual, then it inherits the nearest definition for that function. However, any virtual functions that the class does contain must be defined. It is often a source of mysterious error messages from compilers to declare but not define a virtual function.

Overriding: A derived-class member function overrides a function with the same name in the base class if the two functions have the same number and types of parameters and both (or neither) are const. In that case, the return types must also match, except that as in §13.4.2/246, if the base-class function returns a pointer (or reference) to a class, the derived-class function can return a pointer (or reference) to a derived class. If the argument lists don't match, the base- and derived-class functions are effectively unrelated.

virtual destructors: If a pointer to the base class is used to delete an object that might actually be a derived-class object, then the base class needs a virtual destructor. If the class has no other need for a destructor, then the virtual destructor still must be defined and should be empty:

    class base {
    public:
        virtual ~base(){ }
    };

As with any other function, the virtual nature of the destructor is inherited by the derived classes, and there is no need to redefine the destructor in the derived classes.
---
Also from 《Accelerated C++》. 其实这第三个问题我知道什么时候需要一个destructor,就是总是无法精确地表达这层意思,关键还是没做过实际的C++项目,印象不深刻。

No comments:

Post a Comment