How can one force the compiler to make the default destructor of a class non-inline?
One way of doing this is to write an empty destructor definition, but it feels messy and also you get a warning from the static analyzer (clang-tidy in my case), that = default should be used for a trivial destructor.
To elaborate more on the actual use case - the goal is to have something similar to:
MyClass.h
class MyClassImpl;
class MyClass {
std::unique_ptr<MyClassImpl> m_impl;
public:
MyClass();
// and some other methods
};
A std::unique_pointer to an incomplete type, which is forward declared in the header and the definition is known only in the source file.
The code above will give a compiler error:
error: use of undefined type 'MyClassImpl'
The actual problem is, that the default destructor of MyClass generated by the compiler is inline and so it needs the complete type info of MyClassImpl.
This can be fixed by adding an empty destructor for MyClass (by declaring in the header and defining in the source file, since defining in the header will implicitly make it inline which will cause the same error).
But is this the only way in modern C++?
Just implement it in cpp file as ordinary method:
MyClass.h
class MyClassImpl;
class MyClass {
std::unique_ptr<MyClassImpl> m_impl;
public:
MyClass();
~MyClass() /*noexcept*/;
// and some other methods
};
in cpp
MyClass::~MyClass() /*noexcept*/ = default;
Related
I have been provided with a header file that includes a base class declaration. Within the class declaration is a virtual destructor that has been defined. From this, we need to code the implementation (.cpp) file. The code looks like this in the header file:
class MyClass
{
private: ...
protected: ...
public:
MyClass (double aBaseValue = 0.0);
virtual ~MyClass() { }
...
};
What I am struggling with is what code is required in the implementation (.cpp) file for the destructor. I thought that because I have defined it within the class declaration I do not need to define it again in the implementation file, but if I leave it out then I get the following error in the class declaration when hovering over my virtual destructor, as well on the constructor definition in my .cpp file.
undefined reference to `vtable for MyClass'
SO, if I instead add the following code to the source file MyClass::~MyClass(); like so
#include "MyClass.h"
MyClass::MyClass(double aBaseValue)
{
this->fBaseValue = aBaseValue;
{
MyClass::~MyClass();
then the first two errors go away, but now I'm given an error over the destructor code in the .cpp file
declaration of 'virtual MyClass::~MyClass()' outside of class is not definition [-fpermissive]
From what I can understand, the above error is telling me that I am basically trying to declare the destructor again as there is no braces... but if I put braces a get an error stating that there is a redefinition of the destructor.
I'm not sure what my other options are. Can someone please help me understand how I am supposed to be implementing a virtual destructor for both the class declaration and implementation? Thanks.
I can't find the answer anywhere. It can be done by using condition and throwing exception but is there any other way to do so?
It isn't clear why you would want a class that cannot be constructed under any circumstances, but you could make all constructors private and provide no implementation for them. This will prevent construction at compile time.
In C++11 you can use delete for all the constructors:
class A
{
public: // or private, doesn't matter.
A()=delete;
A(const A&)=delete;
A(A&&)=delete;
};
Well, this is a bit of an awful hack but quite frankly any C++ application which needs a way to define an unconstructable object is probably already an awful hack!
class la
{
public:
virtual void oh_no_you_dont() = 0;
};
int main()
{
la an_instance;
return 0;
}
And under GCC, I get the following:
test.cpp: In function ‘int main()’:
test.cpp:9: error: cannot declare variable ‘an_instance’ to be of abstract type ‘la’
test.cpp:2: note: because the following virtual functions are pure within ‘la’:
test.cpp:4: note: virtual void la::oh_no_you_dont()
You can make all constructors private. This way it's impossible to create an instance of the class. You can then supply one or more static factory methods for creating the class, and by this make the users use only factory methods.
Do you want your class to prevent from being constructed?
Here is a solution with an old C++ standard e.g. C++03 and older
class A {
private:
A();
A(const A&)
A(A&&);
~A()
};
Here is a solution using the latest C++ standard e.g. C++11, C++14, C++17, C++20
class A
{
A()=delete;
A(const A&)=delete;
A(A&&)=delete;
};
or even
class A final {
~A() = delete;
}
final means that a class cannot be inherited from.
delete for a destructor means that you can not destruct a class
Prohibiting a destructor blocks you from constructing an object also.
Why do we want to prohibit objects from being constructed/destructed?
A very common use case is that a developer wants to create a "static" class in C++.
"static" class in C++ means a class with only static methods.
This pattern is also know as an "util" class.
Instead of defining a class many people advice to use a canonical namespace that contains static functions for this purpose.
I am new at building distributable libraries written in C++ and I am getting a bit lost.
I have created a .cpp file with wrappers for all functions I want the library to offer users, and I have written 2 .h files, one public and one private. Below is a dummy example of my header files:
public.h:
class myclass
{
public:
public_function();
private:
}
private.h:
class myclass
{
public:
public_function();
private:
anotherClass instanceofClass;
}
Note that the implementation of public_function() uses the "instanceofClass" in the code.
I have been able to compile with no problem the code using the private class and to compile and link the library with external programs using the public header and the compiled library. When executing that code, though, I am getting segmentation faults that I suspect have to do with lack of proper initialization of "instanceofClass".
Am I doing the right thing? Am I forced to instantiate "instanceofClass" inside the implementation of public_function() for it to be initialized properly, or is there anything else I should do instead?
Thanks a lot.
You can't declare the same class 'myclass' in two different ways. There has to be a single class definition. If you want to hide the implementation's API you want to use the 'Pimpl' idiom. So your public class has a single pointer to a private class. For example:
public.h
class myclass_private;
class myclass {
private:
myclass_private* pimpl;
public:
myclass();
void public_function();
};
public.cpp
myclass::myclass() {
pimpl = new myclass_private;
}
void myclass::public_function() {
pimpl->private_function();
}
private.h
class myclass_private {
public:
void private_function();
};
The myclass defined in public.h has no members, and is therefore sized 1 byte. The myclass defined in private.h encapsulates anotherClass, and is therefore whatever size anotherClass is. This inconsistency is the root of your problem.
What you ought to do is have only one header, and use a pointer (which doesn't require a class definition) to enable hiding the implementation of anotherClass. I'll repeat Joachim's link to the pimpl idiom for elaboration.
The definition of a class shall not changr between different translation units. This is one of the aspects of the One Definition Rule. What you might want to donis to define the publicly visible class to have a pointer to a private implementation: the Pimpl Idiom:
class Public {
public:
...
private:
struct Impl;
Impl* impl_;
};
The struct Impl would only be defined in the implementation file.
Your class lacks a proper constructor, which means that the compiler will provide a default one based on the content of the class definition. If that definition isn't consistent accross all the code, it won't get initialized the same way everywhere, and some data may be missing.
If you want to hide the implementation details of instanceofClass, just do a forward declaration in the header (the private header you're providing is correct, you can use it as your public one), and provide an implementation somewhere in your code.
i have a variable that i prefer to declare in a cpp file instead of the header file. It should be accessible to objects of that class only. This variable should have a separate copy for every object of that class. Inheritance is not necessary.
Normally, I'd just declare it in the class definition.
A.h:
class A {
private:
int number;
}
But, can I do this instead?
B.h:
class B {
private:
// nothing
}
B.cpp:
static int number;
No, if you take the second approach, you're making it a static variable, which means you won't have a different copy for each object of that class (they'll all share that variable).
Either way, if it should only be accessed by that class, it should go in the class declaration, and should not be a global variable. By making it a static global variable, you're restricting access just to the scope of the file, not to the class. As good programming practice, try using as few global variables as possible.
If your goal is to hide implementation details from a customer who only sees your header files (either for secrecy, or to avoid dependencies on library internals), the design pattern you're looking for is the pimpl pattern ("pointer to implementation").
myclass.h:
class MyClassImpl;
class MyClass
{
public:
MyClass();
~MyClass();
int someFunc();
private:
MyClassImpl * pimpl;
}
myclass.cpp:
class MyClassImpl
{
public:
MyClassImpl();
int someFunc();
private:
// whatever members you actually need
}
MyClass::MyClass()
{
pimpl = new MyClassImpl();
}
MyClass::~MyClass()
{
delete pimpl;
}
int MyClass::someFunc()
{
return pimpl->someFunc();
}
// go on implementing MyClassImpl as you would have implemented MyClass
Beware: This example code does not have proper copy semantics. You might want to use some smart pointer instead, or implement the proper copy constructor / assignment operator shenannigans.
It is possible to hide data members in the cpp file using the private implementation idiom.
//a.hpp
struct AData;
class A
{
public:
A();
private:
AData* data_members;
};
//a.cpp
struct AData
{
int number;
};
A::A(): data_members(new AData()) {}
Not sure if it pays off with just one integer. But this can be used to reduce compile times: you can modify A's "data members" and implementation at will without having to recompile files including a.hpp.
Also, prefer a suitable smart pointer instead of the plain pointer (one that has suitable copy behavior and can be declared with an incomplete type).
This variable should have a separate copy for every object of that class.
Keeping it static wont let you acheive this. It will be one copy shared by all instances.
If you want each object to have its own copy of number then you will have to make it an member of your class.
If you want a separate copy for every object of your class, you need to declare it in the header file or have some sort of static map between the object value and the value for that object that is initialized by the object constructor.
If you want a variable to be associated with a class object, it has to be declared inside the class. All the object data should be inside the class.
That is called Encapsulation.
I want to use forward declaration of a class in my software, so I can have typedefs
and use them inside the class full declaration.
Smth like this:
class myclass;
typedef boost::shared_ptr<myclass> pmyclass;
typedef std::list<pmyclass > myclasslist;
class myclass : public baseclass
{
private: // private member declarations
__fastcall myclass();
public: // public member declarations
__fastcall myclass(myclass *Parent)
: mEntry(new myclass2())
{
this->mParent = Parent;
}
const myclass *mParent;
myclasslist mChildren;
boost::scoped_ptr<myclass2> mEntry;
};
so my question is:
are there any drawbacks in this method? I recall some discussion on destructor issues with forward declaration but I did not get everything out of there.
or is there any other option to implement something like this?
Thanks.
EDIT:
I found the discussion I was referring to: here
The main drawback is everything. Forward declarations are a compromise to save compilation time and let you have cyclic dependencies between objects. However, the cost is you can only use the type as references and can't do anything with those references. That means, no inheritance, no passing it as a value, no using any nested type or typedef in that class, etc... Those are all big drawbacks.
The specific destruction problem you are talking about is if you only forward declare a type and happen to only delete it in the module, the behavior is undefined and no error will be thrown.
For instance:
class A;
struct C
{
F(A* a)
{
delete a; // OUCH!
}
}
Microsoft C++ 2008 won't call any destructor and throw the following warning:
warning C4150: deletion of pointer to incomplete type 'A'; no destructor called
: see declaration of 'A'
So you have to stay alert, which should not be a problem if you are treating warnings as errors.
From the C++ standard:
5.3.5/5:
"If the object being deleted has incomplete class type at the point of
deletion and the complete class has a non-trivial destructor or a
deallocation function, the behavior is undefined."