Consider the following example where the construction of Derived class takes a pointer on its constructor's initializer list. Of course I want to check if this pointer is valid and throw an exception otherwise.
My attempt prevents the program to crash but Base part is still constructed before I can throw the exception.
Is there a way I can prevent Base class constructor being called in this case ?
#include <stdlib.h>
#include <iostream>
class Base
{
public:
Base(int val) : val_b(val)
{
std::cout << "Base::CTOR" << std::endl;
}
~Base() { }
int val_b;
};
class Derived : public Base
{
public:
Derived(int *, int);
~Derived() { }
int val_d;
void print(void)
{
std::cout << "Base:\t" << val_b << std::endl;
std::cout << "Derived:" << val_d << std::endl;
}
};
Derived::Derived(int *val1, int val2) : Base(val1 ? *val1 : -1), val_d(val2)
{
if (!val1)
{
throw std::invalid_argument("bad pointer");
}
}
int main()
{
int *a = NULL;
int b = 43;
try
{
Derived *d = new Derived(a, b);
d->print();
}
catch (std::exception &e)
{
std::cout << "Exception: " << e.what() << std::endl;
}
return 0;
}
You might call a function/lambda before calling Base constructor:
Derived::Derived(int *val1, int val2) :
Base([&](){
if (!val1) {
throw std::invalid_argument("bad pointer");
}
return *val1;
}()),
val_d(val2)
{
}
Maybe I misunderstand your question, but consider this simplified example:
#include <iostream>
struct Base {
~Base() { std::cout <<"destructor";}
};
struct Foo : Base {
Foo() : Base() {
throw 1;
}
};
int main()
{
try {
Foo f;
} catch(...){}
}
Output is:
destructor
My attempt prevents the program to crash but Base part is still constructed before I can throw the exception.
That isn't a problem. As always with exceptions, stack is unwinded and the Base part of Foo is properly destroyed. I see nothing wrong in your code (in the sense of seriously broken, though design is debatable). If construction fails and you throw an exception in the body of the constructor, cleaning up what already has been constructed is the best you can do.
I don't get why you want it but anyway have you tried failing in Base ctor rather than Derived ctor?
class Base
{
public:
Base(int *val)
{
if (!val)
{
throw std::invalid_argument("bad pointer");
}
val_b = val;
std::cout << "Base::CTOR" << std::endl;
}
~Base() { }
int val_b;
};
Related
I have a use case of unions, but as many programmers I quite find it ugly to use unions. So I tried using exception handling not in the way it is meant to be. I understand that this will introduce some loss of time due to handling of exceptions. My question is : is there a clean way to do that ?
here is the code, with union, and without
//g++ 7.4.0
#include <iostream>
using namespace std;
class C{ int i ; public : C(int i):i(i){cout << "C(" << i << ")\n";} void display() const { cout << "#C(" << i << ")\n"; } };
class D{ int i ; public : D(int i):i(i){cout << "D(" << i << ")\n";} void display() const { cout << "#D(" << i << ")\n"; } };
class E{ int i ; public : E(int i):i(i){cout << "E(" << i << ")\n";} void display() const { cout << "#E(" << i << ")\n"; } };
struct CDE { enum {C_t,D_t,E_t} kind; union { C c; D d; E e; }; CDE(){} };
CDE f(int i){
CDE res;
if( i==1 ) { res.kind = CDE::C_t; res.c = C(1); return res; }
if( i==2 ) { res.kind = CDE::D_t; res.d = D(2); return res; }
res.kind = CDE::E_t; res.e = E(i); return res;
}
void g(int i){
if( i==1 ) throw C(1);
if( i==2 ) throw D(2);
throw E(i);
}
int main(){
cout << "/** trace\n\nusing union\n";{
CDE res = f(1);
if (res.kind==CDE::C_t){ res.c.display(); }
if (res.kind==CDE::D_t){ res.d.display(); }
if (res.kind==CDE::E_t){ res.e.display(); }
}cout << "\nusing exceptions\n";{
try{
g(1);
}
catch(const C& c){ c.display(); }
catch(const D& d){ d.display(); }
catch(const E& e){ e.display(); }
}cout << "\nstop\n*/\n";
}
and here it the (obvious) trace I get
/** trace
using union
C(1)
#C(1)
using exceptions
C(1)
#C(1)
stop
*/
I'd strongly suggest against using exception for this, it's error-prone, and not what they are meant for.
One of the issue would be extensibility. Using exception, say you add one type, you have to be sure you've add it to your try-catch statement. Moreover, it's a bad habit, because it break the usual code flow. (say you add something after g(), it will never be called.
Another issue is that if there are actual exception, you would have logic mixed with error handling in the same catch block, which would then become harder to read. Or you might have code throwing an exception while an exception was already thrown, which would stop the execution altogether.
If you want to use union, you could use std::variant, or use a switch statement on your enum (which is better than using ifs one after the other.)
However, in C++, and most Object Oriented language, there is a better way to achieve what you want here, using inheritance:
class C{ int i ; public : C(int i):i(i){cout << "C(" << i << ")\n";} void display() const { cout << "#C(" << i << ")\n"; } };
class D{ int i ; public : D(int i):i(i){cout << "D(" << i << ")\n";} void display() const { cout << "#D(" << i << ")\n"; } };
class E{ int i ; public : E(int i):i(i){cout << "E(" << i << ")\n";} void display() const { cout << "#E(" << i << ")\n"; } };
In your code here, we can see that all these classes have a common interface (understand here, a common "shape", they all have a void display() const method.
We could generalize all these class as the "same" as this one (at least if the logic inside their method is ignored)
class displayable {
public:
void display() const;
};
Now, this will be a common "type". However, we want all three class to be able to either implement, or override the function display. let's change this:
class i_displayable {
public:
virtual ~i_displayable(){}
virtual void display() const = 0;
};
class displayable {
public:
virtual ~displayable() {}
virtual void display() { std::cout << "displayable with default implementation" << std::endl;}
};
So, what is the differences between those two:
i_displayable declare display as a pure virtual member. What that mean is that any class inheriting from i_displayable will have to implement display()
displayable declare display() as a virtual member, and provide an implementation. This will allow inheriting class to override the function.
I'll get to why both declare a virtual destructor in an instant.
Let's rewrite class C for now.
class C : public displayable {
int i;
public:
C(int i): i(i) { std::cout << "C(" << i >> ")" << std::endl;}
virtual ~C(){}
void display() const override {
std::cout << "#C(" << i << ")" << std::endl;
}
}
So, we've override the display function (the override keyword is optionnal), and we've said that C inherits from displayable publicly.
What this means is that we can now consider any pointer to a class C instance as a pointer to a displayable instance. As the function display is marked as virtual, when using a pointer do displayable, the function from C will be called, if it exists, and the one in displayable will be called if it does not.
That actually the reason behind making the destructor virtual. You don't want do destruct a displayable, but the actual instance (C in our case)
Now, let's say you've done this on C, D and E, your calling code can be rewritten as:
std::shared_ptr<displayable> f(int i){
std::shared_ptr<displayable> res;
if( i==1 ) { res = std::make_shared<C>(1); }
else if( i==2 ) { res = std::make_shared<D>(2); }
else { res = std::make_shared<E>(i);
return res;
}
int main(){
cout << "/** trace\n\nusing union\n";{
std::shared_ptr<displayable> res = f(1);
res->display();
}
}
Using Try Catch based Exceptional Handling seems coding-friendly in most cases
There are no conditional statements needed for run time exception handling using try-catch like your code shows. I would personally use Exceptions using Try Catch as you did.
try{
g(1);
}
catch(const C& c){ c.display(); }
catch(const D& d){ d.display(); }
catch(const E& e){ e.display(); }
I found a problem while using 3rd party code which cannot be altered. I need to make a copy of object member. I can't do this strictly because one of inner members has private assignment operator. The only solution I found is tricky so I want to ask you if you see any red lights that can affect my program.
Here's the simplified code I'm dealing with (remember that I cannot change it!):
#include <iostream>
#include <algorithm>
class MBool
{
public:
MBool() {};
MBool(const MBool& arg) {}
private:
MBool& operator=(const MBool& arg);
};
class InnerContent {
private:
int* pBuffer;
public:
InnerContent() {
pBuffer = new int[20];
std::cout << "InnerContent()" << std::endl;
}
InnerContent(const InnerContent& otherInnerContent) {
pBuffer = new int[20];
std::copy(otherInnerContent.pBuffer, otherInnerContent.pBuffer + 20, pBuffer);
std::cout << "InnerContent(const InnerContent&)" << std::endl;
}
~InnerContent() {
std::cout << "~InnerContent()" << std::endl;
delete [] pBuffer;
pBuffer = nullptr;
}
virtual void someVirtualFunction() {}
};
class Content {
public:
InnerContent innerContent;
int someNumber;
MBool boolVar;
Content() {
std::cout << "Content()" << std::endl;
}
~Content() {
std::cout << "~Content()" << std::endl;
}
Content(const Content& otherContent) :
innerContent(otherContent.innerContent),
someNumber(otherContent.someNumber),
boolVar(otherContent.boolVar)
{
std::cout << "Content(const Content&)" << std::endl;
}
virtual void someVirtualFunction() {}
};
class A {
public:
Content content;
A() { std::cout << "A()" << std::endl; }
~A() { std::cout << "~A()" << std::endl; }
};
class B {
public:
Content content;
B() { std::cout << "B()" << std::endl; }
~B() { std::cout << "~B()" << std::endl; }
};
And here's what I'm about to do with it (only this code can be modified and extended):
void copyContent(Content& contentFrom, Content& contentTo) {
contentTo.~Content();
new (&contentTo) Content(contentFrom);
};
int main() {
A a;
B b;
// I wish to do this:
//b.content = a.content;
// but Content class has no operator= function implemented
// also I can't use generated assignment operator function because of MBool::operator= is private
// The only work-around I found is this:
std::cout << "--- Before copying" << std::endl;
copyContent(a.content, b.content);
std::cout << "--- After copying" << std::endl;
}
My solution is to call Content destructor manually to free any dynamically allocated memory in Content and its inner classes. Memory on the stack remains untouched so I can reuse it with placement-new operator that calls copy constructor that is present and does exactly what I need. When main function scope ends 'a' object is cleaned up properly.
Code output:
InnerContent()
Content()
A()
InnerContent()
Content()
B()
--- Before copying
~Content()
~InnerContent()
InnerContent(const InnerContent&)
Content(const Content&)
--- After copying
~B()
~Content()
~InnerContent()
~A()
~Content()
~InnerContent()
I don't want to make my own function that copies all the fields because this class can be updated in new version and there may be additional field that I will not copy and most probably no one will remember to fix it.
Question: Do you think this may cause any memory leaks or memory corruption? Do you see any problems that I didn't mention?
Basically the Idea should work. To protect yourself from forgetting to call the destructor, I think, you should wrap the whole think in a kind of smart pointer like class template. In this example it actually does not wrap a pointer, but the content object itself.
template <typename ContentType>
class content_wrapper {
private:
ContentType content_;
public:
content_wrapper() : content_ {} {};
content_wrapper(const content_wrapper& other) :
content_{other.content_} {};
content_wrapper& operator = (const content_wrapper& other) {
content_.~ContentType();
new (&content_) ContentType(other);
return *this;
}
ContentWrapper& operator * () {
return content_;
}
ContentWrapper* operator -> () {
return &content_;
}
};
now you can use it like that:
class A {
public:
content_wrapper<Content> content;
A() { std::cout << "A()" << std::endl; }
~A() { std::cout << "~A()" << std::endl; }
};
class B {
public:
content_wrapper<Content> content;
B() { std::cout << "B()" << std::endl; }
~B() { std::cout << "~B()" << std::endl; }
};
int main() {
A a;
B b;
b.content = a.content; // the wrapper will take care.
b.content->someVirtualFunction();
}
Easy to read and you can never forget the destructor call, whenever you want to assign a content object.
I am learning C++. I have a base class, Base, and its derived class, Derived. And they are push_back into std::vector<Base*> vec. Assuming vec[0] == &Base and vec[1] == &Derived, I can switch function for vec[0] and vec[1] without virtual function. The code is at the end of this question. Is there better way to do it without virtual function? I want pure data classes and I want to add non-member functions to modify them to avoid modifying code of data classes. Thank you very much.
class TypeInterface {
public:
virtual int type(void) = 0;
virtual ~TypeInterface() {}
};
class Base : public TypeInterface {
public:
static constexpr int type_ = 1;
virtual int type(void) {
return type_;
}
virtual ~Base() {}
};
class Derived : public Base {
public:
static constexpr int type_ = 10;
virtual int type(void) {
return type_;
}
virtual ~Derived() {};
};
void Function(Base* ptr) {
std::cout << "function for Base" << std::endl;
}
void Function(Derived* ptr) {
std::cout << "function for Derived" << std::endl;
}
void SwitchFunction(int type, void* ptr) {
switch (type) {
case 1: {
Base* original_type_ptr = static_cast<Base*>(ptr);
Function(original_type_ptr);
break;
}
case 10: {
Derived* original_type_ptr = static_cast<Derived*>(ptr);
Function(original_type_ptr);
break;
}
default:
std::cout << "invalid type(=" << type << ")" << std::endl;
}
}
void test_function_selecter(void) {
Base b;
Derived d;
std::vector<Base*> vec;
vec.push_back(&b);
vec.push_back(&d);
for (auto e: vec) {
SwitchFunction(e->type(), e);
}
}
You do not need 'type_', or 'int type(void)' instead use 'typeid'
void SwitchFunction(Base* ptr)
{
auto&& type = typeid(*ptr);
if (type == typeid(Base))
Function(dynamic_cast<Base*>(ptr));
else if (type == typeid(Derived))
Function(dynamic_cast<Derived*>(ptr));
else std::cout << "invalid type(=" << type.name() << ")" << std::endl;
}
Unfortunately this probably does not answer your question properly as it requires 'Base' to have a virtual function (such as a destructor, whish is generally recommended to be virtual whenever your type is involved in hierarchies)
Can somebody explain my why my factory function is correct? Is unique_ptr doing dynamic casts by default? Why does the return type not have to be the same as the factory function type?
#include <exception>
#include <iostream>
#include <memory>
struct Animal
{
virtual void makeSound() { std::cout << "(...)" << std::endl; }
};
struct Cat : public Animal
{
virtual void makeSound() { std::cout << "Meaw!" << std::endl; }
};
struct Dog: public Animal
{
virtual void makeSound() { std::cout << "Woof!" << std::endl; }
};
struct ConfusedCat : public Cat
{
virtual void makeSound() { std::cout << "Moooooh!" << std::endl; }
};
// Why is this factory function allowed like this?
std::unique_ptr<Animal> factory(const int i)
{
if (i == 1)
return std::unique_ptr<Cat>(new Cat());
else if (i == 2)
return std::unique_ptr<ConfusedCat>(new ConfusedCat());
else if (i == 3)
return std::unique_ptr<Dog>(new Dog());
else
return std::unique_ptr<Animal>(new Animal());
}
int main()
{
try
{
auto animal0 = factory(0);
auto animal1 = factory(1);
auto animal2 = factory(2);
auto animal3 = factory(3);
animal0->makeSound();
animal1->makeSound();
animal2->makeSound();
animal3->makeSound();
}
catch ( std::exception &e )
{
std::cout << e.what() << std::endl;
return 1;
}
return 0;
}
In C++ derived to public base pointer conversion is implicit, no cast is required.
The same holds true for all standard and boost smart pointers.
See overload 6 on std::unique_ptr::unique_ptr:
std::unique_ptr<Derived> is implicitly convertible to std::unique_ptr<Base> through the overload (6)
It's hard to explain exactly what I want to do here, but I have a base class and two classes which inherit this base class. Both classes which inherit it have their own unique members. I want to be able to pass both to a method, and have that method detect which it is, then access their unique members. I can't assume there will only be two classes which inherit it, so i'm looking for something of a more general solution.
Here is an example of what I'd like to do:
#include <iostream>
class Base {
public:
int _type;
Base() { }
};
class First : public Base {
public:
int _first_only;
First() { }
};
class Second : public Base {
public:
int _second_only;
Second() { }
};
void test (Base b) {
std::cout << "Type: " << b._type << std::endl;
if(b._type==1) {
std::cout << "First\n";
// Want to be able to do this
std::cout << "Val: " << (First)b._first_only << std::endl;
} else if(b._type==2) {
std::cout << "Second\n";
// And this
std::cout << "Val: " << (Second)b._second_only << std::endl;
}
}
int main() {
First f;
f._first_only=1;
f._type=1;
Second s;
s._type=2;
s._second_only=2;
test(f);
test(s);
}
This is similar to others answers:
You can write polymorphic classes to get this behavior using virtual functions.
Pass the Dervied class objects either by pointer or by reference to get polymorphic behaviour. Otherwise it will lead to object slicing. Your test() function leads to object slicing.
This code may also help you. You can see that there are different ways to print the type. I used GetBaseType(), GetDerivedType() and GetType(). Among these GetType() method is convenient for you case. There are two constructors for convenience. Constructors allow to initialize data members.
class Base {
private:
int _type;
public:
Base(int type) : _type(type) { }
int GetBaseType() { return _type; }
virtual int GetDerivedType() = 0;
virtual int GetType() { return _type; }
};
class First : public Base {
private:
int _first_only;
public:
First() : Base(1), _first_only(1) { }
First(int first_only) : Base(first_only), _first_only(first_only) { }
int GetDerivedType() { return _first_only; }
virtual int GetType() { return _first_only; }
};
class Second : public Base {
private:
int _second_only;
public:
Second() : Base(2), _second_only(2) { }
Second(int second_only) : Base(second_only), _second_only(second_only) { }
int GetDerivedType() { return _second_only; }
virtual int GetType() { return _second_only; }
};
void test (Base &b) {
std::cout << "Type: " << b.GetBaseType() << std::endl;
std::cout << "Type: " << b.Base::GetType() << std::endl;
std::cout << "Dervied type: \n";
std::cout << "Val: " << b.GetDerivedType() << std::endl;
std::cout << "Val: " << b.GetType() << std::endl;
}
int main() {
First f(1);
Second s(2);
test(f);
test(s);
First f1;
Second s1;
test(f1);
test(s1);
}
Either declare a virtual function in Base
Move the common members types from First and Second into Base.
For your specific problem, 2nd option is better:
class Base {
public:
int _member; // have getter() method, if '_member' is private
Base() { }
};
Inside, test():
void test (Base &b) { // <--- practice to pass by reference if copy is not needed
// use b._member;
};
Your code does not work polymorphically, because you are passing the function-parameter by value, which results in slicing.
If you have a method that does different things for different types, consider overloading it for each of these types.
Three things I'd do:
In general switching on type codes is not considered good object oriented design: Instead pull the switched code into the classes.
I'd also set up the type tags in the constructor of the specific classes.
And as others have mentioned you need to pass the argument by reference to avoid slicing.
Here's what the code would look like:
#include <iostream>
class Base {
public:
int _type;
Base() { }
virtual void print_to_stream( std::ostream & os ) const =0;
};
class First : public Base {
public:
int _first_only;
First() { _type =1; }
void print_to_stream( std::ostream & os ) const
{
os<<"First\n";
os<<"Val: " << _first_only << std::endl;
}
};
class Second : public Base {
public:
int _second_only;
Second() { _type=2; }
void print_to_stream( std::ostream & os ) const
{
os << "Second\n";
os << "Val: " << _second_only << std::endl;
}
};
void test (Base & b)
{
std::cout << "Type: " << b._type << std::endl;
b.print_to_stream( std::cout );
}
int main() {
First f;
f._first_only=1;
Second s;
s._second_only=2;
test(f);
test(s);
}