Very good observation. I am actually using C++ 11. With C++ 11, cout is guaranteed to be initialized before other global variables. With older standard, you do have the Fiasco problem with cout.
Great tutorials Bo, Congrats! Just a note, in C++11 you should use the nullptr keyword to initialize pointers instead of 0 or null for these operations.
In the last example (6:35) you remove the meow call from the dog constructor - if you would not do that - there would be an infinite constructor calls for both cat and dog: So, if meow is called in the dog constructor - the cat is null so cat constructor called - cat constructor calls bark - the dog is still null so dog constructor is called again etc... Is there a way to deal with this? (maybe with some additional variable to check for a partially constructed class?)
tematum , think about two normal functions each calling the other? It will create a loop. Same with constructor calling other constructor which calls back the caller, it will create infinite loop until stack overflow happens and program terminate.
No, there would not be an infinite constructor calls even there would be meow call in the dog constructor. You missing something: after ..cat constructor calls bark- the dog is is not null because before program comes that point, main function called Singleton::getDog() and there is a static dog pointer initialized with a new dog object. In the Cat constructor the initialized dog object returned. Be carefull by the 'static' declaration.
Hi! Thank you very much for your great tutorials! I have a question about this design pattern.. Wouldn't it be safer to have an argument in the constructor of both classes so that we are sure the objected has been created? In that case we make sure that the object we want to make, will not be initialized unless we pass the correct input arguments. For example the Cat class would become: Cat::Cat(char* name, Dog* dog) { cout
😩Surprisingly my C++ 14 gnu compiler works without crashing when I use global variables in both dog n cat classes’s constructor and do interchange etc. I can’t even reproduce the error you found before using singleton. Program runs perfectly fine
I define Meyer's Singleton so we don't need to have member data variables of static types: #ifndef Singleton_H #define Singleton_H #include "Dog.h" #include "Cat.h" class Singleton { public: static Dog* getDog();
Very good observation. I am actually using C++ 11. With C++ 11, cout is guaranteed to be initialized before other global variables. With older standard, you do have the Fiasco problem with cout.
Great tutorials Bo, Congrats! Just a note, in C++11 you should use the nullptr keyword to initialize pointers instead of 0 or null for these operations.
I'm sure he's aware :)
All videos on advanced C++ are excellent... Upload videos on more pitfalls and design approach to solve them. New topics also..
You should not check if pointer is not equal to 0 before deleting it, standard guarantees that delete 0 will do nothing.
ourdyingrepublic, I believe calling delete is more overhead as compared to checking if()
I believe, the order of initialization depends on order of linkage.
It does not look very intuitive for a user that he has to create an instance of singleton just to ensure its destructor is called...
In the last example (6:35) you remove the meow call from the dog constructor - if you would not do that - there would be an infinite constructor calls for both cat and dog:
So, if meow is called in the dog constructor - the cat is null so cat constructor called - cat constructor calls bark - the dog is still null so dog constructor is called again etc...
Is there a way to deal with this? (maybe with some additional variable to check for a partially constructed class?)
tematum , think about two normal functions each calling the other? It will create a loop. Same with constructor calling other constructor which calls back the caller, it will create infinite loop until stack overflow happens and program terminate.
No, there would not be an infinite constructor calls even there would be meow call in the dog constructor. You missing something: after ..cat constructor calls bark- the dog is is not null because before program comes that point, main function called Singleton::getDog() and there is a static dog pointer initialized with a new dog object. In the Cat constructor the initialized dog object returned. Be carefull by the 'static' declaration.
Hi! Thank you very much for your great tutorials!
I have a question about this design pattern..
Wouldn't it be safer to have an argument in the constructor of both classes so that we are sure the objected has been created?
In that case we make sure that the object we want to make, will not be initialized unless we pass the correct input arguments.
For example the Cat class would become:
Cat::Cat(char* name, Dog* dog)
{
cout
Is there no need for any include statements in main.cpp
Why is there an extern Dog d but no extern Cat c("Smokey") ?
Because 'Cat c' is declared and used in same source.
Dog d in cat.cpp is used from the main.cpp
getCat and getDog functions can be implemented even simpler, with following code:
static Dog& getDog()
{
static Dog dog;
return dog;
}
😩Surprisingly my C++ 14 gnu compiler works without crashing when I use global variables in both dog n cat classes’s constructor and do interchange etc. I can’t even reproduce the error you found before using singleton. Program runs perfectly fine
Not a good example of why one should use singleton. In fact, not sure if static objects should ever be created.
I define Meyer's Singleton so we don't need to have member data variables of static types:
#ifndef Singleton_H
#define Singleton_H
#include "Dog.h"
#include "Cat.h"
class Singleton
{
public:
static Dog* getDog();
static Cat* getCat();
static void cleanDog();
static void cleanCat();
private:
Singleton() = default;
};
#endif
#include "Singleton.h"
Dog* Singleton::getDog()
{
static Dog* pDog = nullptr;
if (pDog == nullptr)
{
pDog = new Dog("Gunner");
}
return pDog;
}
Cat* Singleton::getCat()
{
static Cat* pCat = nullptr;
if (pCat == nullptr)
{
pCat = new Cat("Smokey");
}
return pCat;
}
void Singleton::cleanDog()
{
Dog* pDog = Singleton::getDog();
if (pDog != nullptr)
{
delete pDog;
pDog = nullptr;
}
}
void Singleton::cleanCat()
{
Cat* pCat = Singleton::getCat();
if (pCat != nullptr)
{
delete pCat;
pCat = nullptr;
}
}
Why do you sure that object "cout" is initialized befor your global objects?
Ok, it was. But you say nothing about that:)
Wow. What a terrible video. Bo, you should probably remove this video.