问题
A template class and a normal class:
template <typename Type>
class Holder
{
public:
Holder(const Type& value) : held_(value)
{
cout << "Holder(const Type& value)" << endl;
}
Type& Ref() { return held_; }
private:
Type held_;
};
class Animal
{
public:
Animal(const Animal& rhs) { cout << "Animal(const Animal& rhs)" << endl; }
Animal() { cout << "Animal()" << endl; }
~Animal() { cout << "~Animal" << endl; }
void Print() const { cout << "Animal::Print()" << endl; }
};
Then I want to instantiate a Holder<Animal>
with this statement Holder<Animal> a(Animal());
, however, it fails. I mean Animal()
is not treated as a temporary object. And this statement doesn't call Holder
's constructor.
If someone could explain? I'm not clear. I'm guessing a
becomes a type here. Then, I use Holder<Animal> a = Holder<Animal>(Animal());
, it works well. So, there are some cases here:
Holder<Animal> a(Animal()); a.Ref().Print(); // error
Holder<Animal> a = Holder<Animal>(Animal()); a.Ref().Print(); // ok
Holder<int> b(4); b.Ref() = 10; cout << b.Ref() << endl; //ok
Can explain? I'm just a little confused with the first statement. And the error information this statement causes:
GCC4.7.2
: error: request for member 'Ref' in 'a', which is of non-class type 'Holder<Animal>(Animal (*)())'
VS10
: error C2228: left of '.Ref' must have class/struct/union
, error C2228: left of '.Print' must have class/struct/union
回答1:
The statement Holder<Animal> a(Animal());
does not create a variable, but declares a function that returns a Holder<Animal>
and that takes a function in parameter. It's usually called the most vexing parse, because of this ambiguity (that one would expect a variable rather than a function declaration).
Herb Sutter explains the different possible syntaxes here. In C++11, a possible solution is:
auto a = Holder<Animal> {};
回答2:
You are victim to the "most vexing parse":
Holder<Animal> a(Animal());
is parsed as a function with name a
, that returns a Holder<Animal>
and takes as parameter another function, which has no parameters and returns an Animal
.
In C++11 you can solve that problem by using uniform initialization:
Holder<Animal> a{Animal{}};
来源:https://stackoverflow.com/questions/18585573/why-this-statement-does-not-call-the-constructors-c