I saw a C++03 example online today.
class Cat {
public:
Cat(const Cat& iCat);
};
I was told that in this case, no default constructor will be automatically generated by compiler. If it is true, this means new Cat object can be created from an existing Cat object.
Can anyone tell me how to create the first Cat object in this case? or kindly correct me if my understanding is wrong.
First of all, the valid answer should be that there is no way to create the first Cat
. The example was probably only pulled out to demonstrate how a user-declared constructor will prevent the implicitly-declared default constructor to be declared.
Now, in spite of this, and purely if the means justifies the ends, there is, however, ways of creating the first cat using a layout-compatible object.
C++11 introduced layout compatibility:
Two standard-layout struct (Clause 9) types are layout-compatible if they have the same number of non-static data members and corresponding non-static data members (in declaration order) have layout-compatible types (3.9).
A standard-layout class is a class that:
- has no non-static data members of type non-standard-layout class (or array of such types) or reference,
- has no virtual functions (10.3) and no virtual base classes (10.1),
- has the same access control (Clause 11) for all non-static data members,
- has no non-standard-layout base classes,
- either has no non-static data members in the most derived class and at most one base class with non-static data members, or has no base classes with non-static data members, and *has no base classes of the same type as the first non-static data member.
A standard-layout struct is a standard-layout class defined with the class-key
struct
or the class-keyclass
.
This means that you can do:
class Cat {
public:
Cat(const Cat& iCat) : x{iCat.x} {}
int x;
};
class foo {
public:
foo(int x) : m_x{x} {}
int m_x;
};
int main() {
foo f{5};
Cat* c1 = reinterpret_cast<Cat*>(&f);
Cat c2 = *c1;
std::cout << c2.x << std::endl; // 5
}
The x
and m_x
members are used to demonstrate the copying of (layout-compatible) members.
Note: As mentioned in comment by @M.M, you might need to disable strict aliasing in your compiler for this to work.