Unexpected out (virtual function returning string) - c++

I am having some trouble with an unexpected output in the following simple code. The output works fine with the base class but I run into trouble with the derived class for some reason.
#include <iostream>
#include <string>
using namespace std;
class vehicle {
public:
string* name;
vehicle() {}
vehicle(const string& inputName) {name = new string(inputName);} //constructor
virtual ~vehicle() {delete name; name = nullptr;} // always make base class destructor virtual
//vehicle(const vehicle& rhs) {*this = rhs; cout << "copy called" << endl;} //copy constructor
vehicle& operator=(const vehicle& rhs) {
cout << "assignment called" << endl;
if(this == &rhs){
return *this;
}
name = new string(*rhs.name);
return *this;
} //assignment operator
virtual string& getName() const {return *name; cout << "base" << endl;} //mark function const if we are not going to make any changes to the object
};
class car : public vehicle {
string *title = new string;
public:
car() : vehicle() {}
car(const string& inputName) : vehicle(inputName) {*title = inputName;}
virtual ~car() {}
virtual string& getName() const {string temp = *title; return temp; cout << "derived" << endl;}
};
int main() {
car test("honda");
string temp;
temp = test.getName();
cout << temp;
return 0;
}
I am intending to get the following output:
honda
But am getting:
~weird square boxes~
Edit:
What i'm really trying to accomplish is something like the following in the derived class:
virtual string& getName() const {return "Car: " + *name;}
Before I get enflamed for using the heap for the string, please know that I am only experimenting here. It is my understanding that this should, in theory, work.

This function
virtual string& getName() const {string temp = *title; return temp; cout << "derived" << endl;}
invokes undefined behavior because it returns a reference to a local object temp that will not be alive after exiting the function.
You could define the function like
virtual const string& getName() const {return *name;}
and
const string& getName() const override { return *title;}
And the statements after return statements do not have an effect.
Also other your code has drawbacks. For example the copy assignment operator produces a memory leak.
Or you need explicitly to define the destructor for the class car.
Pay attention to that there is no sense to declare data members name and title as pointers to objects of the type std::string. Instead declare data members of the type std::string.

Related

Unique_ptr in a class

The Human class turned out to be non-copied, since it contains a field of type unique_ptr, for which the copy constructor and the copying assignment operator have been removed. This prevents the compiler from automatically generating a copy constructor and assignment operator for the Human class.
How can I implement a copy constructor and a copy assignment operator in the Human class? A copy of the human must own a copy of the cat, if the original human owned it.
struct Cat {
Cat(const string& name, int age)
: name_(name)
, age_(age) //
{
}
const string& GetName() const noexcept {
return name_;
}
int GetAge() const noexcept {
return age_;
}
~Cat() {
}
void Speak() const {
cout << "Meow!"s << endl;
}
private:
string name_;
int age_;
};
unique_ptr<Cat> CreateCat(const string& name) {
return make_unique<Cat>(name, 2);
}
class Human {
public:
explicit Human(const string& name)
: name_(name) {
}
const string& GetName() const noexcept {
return name_;
}
void SetCat(unique_ptr<Cat>&& cat) noexcept {
cat_ = std::move(cat);
}
unique_ptr<Cat> ReleaseCat() noexcept {
return std::move(cat_);
}
private:
string name_;
unique_ptr<Cat> cat_;
};
Your copy constructor might look like
Human::Human(const Human& rhs) :
name_(rhs.name_),
cat_(rhs.cat_ ? std::make_unique<Cat>(*rhs.cat_) : std::nullptr)
{}
but getting rid of std::unique_ptr and having Cat by value (or std::optional<Cat>) would be simpler:
Human::Human(const Human&) = default;
If Cat is polymorphic, a clone method would be required:
Human::Human(const Human& rhs) :
name_(rhs.name_),
animal_(rhs.animal_ ? rhs.animal_->clone() : std::nullptr)
{}

Overload += for a template?

I have a base class Animal and a derived class Bird : Animal. I use a template class that will store vectors of pointers to either Animal or Bird objects. I want to overload the += operator in such a way that I can insert a new animal right in the Atlas, so m_length = m_length + 1, pages.push_back(animal), just to get the idea.
Here's my template class:
template <class T>
class Atlas2 {
public:
int m_length;
std::list<T> pages;
Atlas2() { m_length = 0; }
~Atlas2() {}
void adauga(T data);
T operator+=(const T& data) {
this->m_length++;
this->pages.push_back(data);
return *this;
};
};
And here's the Animal/Bird classes:
class Animal {
protected:
std::string m_name;
public:
Animal() {}
Animal(std::string name) : m_name{name} {}
virtual void set_name(std::string name) { m_name = name; }
virtual std::string get_name() { return m_name; }
virtual std::string regn() const { return "???"; }
virtual ~Animal() { cout << "Destructor animal" << '\n'; }
};
class Bird : public Animal {
public:
bird() : animal() {}
bird(std::string name) : Animal{name} {}
void set_name(std::string nume) { m_name = nume; }
std::string get_name() { return m_name; }
std::string regn() const override { return "pasare"; }
~bird() { cout << "destructor pasare" << '\n'; }
};
However, I can't figure this out. When I use the overloaded += operator in main() like this:
Pasare *c = new Pasare{"vulture"};
Atlas2<Animal *> Atlas;
Atlas += c;
It shows me an error, that it couldn't convert Atlas<Animal *> to <Animal*>.
How should I implement this correctly? Any tip?
Note: The template works fine, I can store in my list pointers to either Animal or Birds without problems, and access their specific methods. I just can't figure out the += part.
You should return Atlas2<T> & not T:
Atlas2<T>& operator+=(const T& data) {
this->m_length++;
this->pagini.push_back(data);
return *this;
};
The basic problem is that you've declared your operator+= as returning a T, but the return statement in it is return *this;, which is an Atlas2<T>.
If you change the return type to Atlas2<T> &, it should work. That's what you would normally want to return from an operator+= anyways, though with your use, it doesn't matter much as you're ignoring the returned value.

Applying the Rule of Five with Inheritance and Virtual Functions

Every example that I've seen which implement the Rule of Five, implements the rule on a class without inheritance and polymorphism (virtual functions).
How can the rule of 5 be applied to the sample code bellow?
The test example uses c-arrays for dynamic objects. This is slightly contrived of course in order to have dynamic objects to manage to demonstrate the Rule of Five. In practice, it could have been anything (FILE ptrs, database handles, etc). Therefore, don't suggest using vector, or turning the exercise into demonstration of the Rule of Zero.
I'd prefer the solution not to use the copy-swap idiom because I find the non-copy-swap method more explicit in the case of non-inheriting classes. But if one wished to illustrate both methods, that would also be great.
Notes about sample code:
B inherits from A.
Both A & B have their own dynamic object to manage (a contrived c-array).
Class T is a contrived class to have custom type for diagnostic prints. The c-arrays store T elements.
Class A & B are void of Rule of Five implementation (to be defined by answer)
The c-arrays have not yet been allocated in the sample code, but of course, they would be at construction based on respective bufferSize.
Sample Code
//TEST TYPE
class T
{
public:
T() { cout << "ctorT" << endl; }
~T() { cout << "dtorT" < endl; }
T(const T& src) { cout << "copy-ctorT " << endl; }
T& operator=(const T& rhs) { cout << "copy-assignT" << endl; return *this; }
T(T&& src) noexcept { cout << "move-ctorT " << endl; }
T& operator=(T&& rhs) { cout << "move-assignT" << endl; return *this; }
}
class A
{
string nameParent = "A";
size_t bufferSizeParent = 0;
T *pBufferParent = nullptr; //c-array
public:
A(string tNameParent, size_t tBufferSizeParent) : nameParent(tNameParent), bufferSizeParent(tBufferSizeParent)
{
cout << "ctorA " << nameParent << endl;
}
virtual ~A(){ cout << "dtorA " << nameParent << endl; }
virtual string getName() { return nameParent; }
virtual void setName(const string name) { nameParent = name; }
};
class B : public A
{
string nameChild = "B";
size_t bufferSizeChild = 0;
T *pBufferChild = nullptr; //c-array
public:
B(string tNameChild, string tNameParent, size_t tBufferSizeChild, size_t tBufferSizeParent)
: A(tNameParent, tBufferSizeParent), nameChild(tNameChild), bufferSizeChild(tBufferSizeChild)
{
cout << "ctorB " << nameChild << endl;
}
~B(){ cout << "dtorB " << nameChild << endl; }
virtual string getName() override final { return nameChild; }
virtual void setName(const string name) override final { nameChild = name; }
};
A good rule of thumb is that a class should directly manage at most one resource. Other classes have all defaulted special members, preferably implicitly, but explicitly if they are to be declared in some variation.
Your example becomes
struct T;
extern T acquire_T();
extern void release_T(T);
class THandle
{
T handle;
public:
THandle()
: handle(acquire_T()) {}
~THandle() { release_T(handle); }
THandle(const THandle &) = delete;
THandle(THandle && other)
: handle(other.handle)
{ other.handle = {}; }
THandle & operator=(const THandle &) = delete;
THandle & operator=(THandle && other)
{ std::swap(handle, other.handle); }
}
class A
{
std::string nameParent = "A";
std::size_t bufferSizeParent = 0;
THandle tParent;
public:
A() {}
A(std::string tNameParent, std::size_t tBufferSizeParent) : nameParent(tNameParent), bufferSizeParent(tBufferSizeParent)
{ }
virtual ~A() = default;
A(const A &) = default;
A(A &&) = default;
A & operator=(const A &) = default;
A & operator=(A &&) = default;
virtual string getName() { return nameParent; }
virtual void setName(const string name) { nameParent = name; }
};
class B : public A
{
std::string nameChild = "B";
std::size_t bufferSizeChild = 0;
THandle tChild;
public:
B() {}
B(string tNameChild, string tNameParent, size_t tBufferSizeChild, size_t tBufferSizeParent)
: A(tNameParent, tBufferSizeParent), nameChild(tNameChild), bufferSizeChild(tBufferSizeChild), bufferChild(std::make_unique(tBufferSizeChild))
{ }
virtual string getName() override final { return nameChild; }
virtual void setName(const string name) override final { nameChild = name; }
};

C++: Pure virtual destructor in abstract class with members

I've just started learning C++ and stumbled across this problem..
I've written this abstract class with pure virtual destructor:
#ifndef ANIMAL
#define ANIMAL
#include <string>
using namespace std;
class Animal {
public:
Animal();
virtual ~Animal() = 0;
Animal(string name, int age);
virtual string says() = 0;
void setName(string name);
void setAge(int age);
string getName() const;
int getAge() const;
private:
int _age;
string _name;
};
inline Animal::~Animal() { }
Created dynamically and destroyed like this...
Animal** animalArray = new Animal*[10];
animalArray[0] = new Dog(name, age);
animalArray[1] = new Cat(name, age);
animalArray[2] = new Owl(name, age);
delete[] animalArray;
and I am left wondering if an Animal object is created dynamically and then destroyed, will the _age and _name members get destroyed properly since the destructor for Animal class is empty? If so, why?
Thanks :D
In the example you posted, you're actually not destroying everything correctly. In the line
delete[] animalArray;
you are deleting an array of Animal*s. Note that this does not automatically destroy the things being pointed to! You would have to do:
for(int i = 0; i < 3; ++i)
delete animalArray[i];
delete[] animalArray;
This destroys each element, then destroys the container.
Now, your actual question is asking whether the private member variables are going to be cleanly destroyed. The answer is yes--after your destructor runs, any statically allocated variables' destructors will also be called by the compiler. It is their obligation to clean up after themselves. When you're doing polymorphism as in your example, the (empty) destructor Animal::~Animal will indeed be called.
Note that this carries the same warning as the code above: if you instead have
string* _name;
that you dynamically allocate in the constructor (with new), then the string* will be destroyed, but the pointed to string will not be. So in that case, you would have to manually call delete to properly clean up.
yes they will. By making the Animal destructor virtual (or pure virtual in your case, doesn't matter regarding your question) you make sure that everything is properly destroyed when using Animal as a base class.
The destructor of Animal will call the destructor for each of it's members in reverse initialization order (i.e. it will destroy _name first and _age afterwards) and thereby makes sure that everything is properly freed.
According to Herb Sutter you cannot instantiate a class with a pure virtual destructor unless it also has a body. The reason is that any derived class will need to call that destructor after its own destructor is finished.
We can verify this with at least one compiler: http://ideone.com/KcwL8W
#include <string>
class Animal
{
public:
virtual ~Animal() = 0;
std::string _name;
};
class Dog : public Animal
{
};
int main() {
Animal* pet = new Dog;
delete pet;
return 0;
}
/home/abDVbj/cc8ghrZk.o: In function `Dog::~Dog()':
prog.cpp:(.text._ZN3DogD2Ev[_ZN3DogD5Ev]+0xb): undefined reference to `Animal::~Animal()'
/home/abDVbj/cc8ghrZk.o: In function `Dog::~Dog()':
prog.cpp:(.text._ZN3DogD0Ev[_ZN3DogD0Ev]+0x12): undefined reference to `Animal::~Animal()'
it will , destructor is not really destroy the object you created , it is called before the object being destroied, if you have not new something in constructor , there is no need for you to delete it.
I try to finger out a sample to prove
when using string(with a pointer member) object as member variable, its destructor will be called, even we do nothing in the class's destructor
so I tried to used a user-defined String as object, so it is easy for us to write some log in the destructor.
it outputs:
constructor is called
constructor is called
constructor is called
operator constructor is called
destructor is called
operator constructor is called
destructor is called
virtual ~Dog()
virtual ~Animal()
destructor is called
it show is when virtual ~Animal() is called , the string object'destructor in the Animal class is called.
we can change the string object to string*(using new in construtor) while still doing nothing in the destructor , and we will see the string's destructor is not called
#include <iostream>
#include <string.h>
using namespace std;
class String{
public:
String(const char *str = NULL);
String(const String &str);
~String();
String operator+(const String & str);
String & operator=(const String &str);
bool operator==(const String &str);
int Length();
friend ostream & operator<<(ostream &o,const String &str);
String SubStr(int start, int end);
private:
char * charArray;
};
String::String(const char *str)
{
if(str == NULL){
charArray=new char[1];
charArray[0]='\0';
}else{
charArray=new char[strlen(str)+1];
strcpy(charArray,str);
}
std::cout<< "constructor is called" << std::endl;
}
String::String(const String &str)
{
std::cout<< "constructor is called" << std::endl;
charArray = new char[strlen(str.charArray)+1];
strcpy(charArray,str.charArray);
}
String::~String()
{
std::cout<< "destructor is called" << std::endl;
delete [] charArray;
}
String String::operator+(const String &str)
{
String res;
delete [] res.charArray;
res.charArray = new char[strlen(charArray)+strlen(str.charArray)+1];
strcpy(res.charArray,charArray);
strcpy(res.charArray+strlen(charArray),str.charArray);
return res;
}
String & String::operator=(const String &str)
{
if(charArray == str.charArray)
return *this;
delete [] charArray;
charArray = new char[strlen(str.charArray)+1];
strcpy(charArray,str.charArray);
std::cout<< "operator constructor is called" << std::endl;
return *this;
}
bool String::operator==(const String &str)
{
return strcmp(charArray,str.charArray) == 0;
}
int String::Length()
{
return strlen(charArray);
}
ostream & operator<<(ostream &o, const String &str)
{
o<<str.charArray;
return o;
}
String String::SubStr(int start, int end)
{
String res;
delete [] res.charArray;
res.charArray = new char[end-start+1];
for(int i=0; i+start<end; i++){
res.charArray[i]=charArray[start+i];
}
res.charArray[end-start] = '\0';
return res;
}
class Animal {
public:
Animal();
virtual ~Animal()=0;
Animal(String name, int age);
public:
int _age;
String _name;
};
Animal::~Animal(){
std::cout << "Animal::~Animal()" << std::endl;
}
Animal::Animal(String name, int age)
{
this->_name = name;
this->_age = age;
}
class Dog :public Animal
{
public:
virtual ~Dog() {
std::cout << "virtual ~Dog()" << std::endl;
};
Dog(String name, int age):Animal(name,age)
{
this->_name = name;
this->_age = age;
}
};
int main(){
Animal* p = new Dog( String("dog"),1);
delete p;
return 0;
}

Proper Class Modeling using C++ and const

Let me preference that I mostly develop in C# and the C++ development which I have done did not fully leverage the C++ language. I am now trying to use the language as it was intended and I am pulling my hair out with const declarations in passed arguments. In the past I never used them or hacked my way into making them work with the STL.
My understanding that I would create the following function when I want to use o as readonly in the function:
void foo(const MyClass* o);
So here is my problem...code first:
#include <iostream>
#include <string>
using namespace std;
///////////////////////////////////////////////////////////
// Classes are defined in the one file for an easy post.
///////////////////////////////////////////////////////////
class ClassA {
private: // member variables
string m_name;
public: // constructors
ClassA(const string& name = "") : m_name{name} {}
virtual ~ClassA() { }
public: // accessors
const string& name() const { return m_name; }
void setName(const string& value) { m_name = value; }
};
class ClassB {
private: // member variables
string m_name;
ClassA m_child;
public: // constructors
ClassB(const string& name = "") : m_name{name} {}
virtual ~ClassB() { }
public: // accessors
const string& name() const { return m_name; }
void setName(const string& value) { m_name = value; }
ClassA* child() { return &m_child; }
void setChild(const ClassA* value) { m_child = *value; }
};
///////////////////////////////////////////////////////////
// Protoptypes are not used to save space for the post.
void doSomethingA(const ClassA* o) {
cout << "name = " << o->name() << endl << endl;
}
void doSomethingB(const ClassB* o) {
cout << "name = " << o->name() << endl << endl;
doSomethingA(o->child());
}
///////////////////////////////////////////////////////////
int main(int argc, char** argv) {
ClassA a { "My Class A" };
ClassB b { "My Class B" };
b.setChild(&a);
b.child()->setName("My New Name");
doSomethingB(&b);
return 0;
}
In main() the compiler (g++ version 4.7.2) balks in doSomethingB:
doSomethingA(o->child());
with error: passing 'const ClassB' as 'this' argument of 'ClassA* ClassB::child()' discards qualifiers [-fpermissive]
Now I am passing my classes to functions as pointers. I plan on always using pointers because I have a problem with the reference/pointer options. I'm choosing one, pointers, and sticking with it. So doSomethingA and doSomethingB I want that to be const to tell the programmer that their class is not being altered. But I only want one version of child() which I want to use sometimes as "read only" and other times allow the user to change the data within the child object (not the best method, I grant that, but there are some use cases where I need this). I even tried:
doSomethingA(const_cast<const ClassA*>(o->child()));
But that did not work.
In the past I removed the const declarations in the functions to make something like this work but now I want to use proper c++. Help please.
try
ClassA* child() const { return &m_child; }
or
const ClassA* child() const { return &m_child; }
to keep the const correctness
Also, you don't need to use pointers as long as you don't plan passing nullptr. So you can do the following:
void doSomethingB(const ClassB& o);
// in class ClassB
const ClassA& child() const { return m_child; }
ClassA& child() { return m_child; }
References still alow polymorphic stuff same way as pointers.
You're attempting to access a non-const function against a const object. You need to make the function const :
const ClassA* child() const { return &m_child; }
You can also provide a const and non-const version:
ClassA* child() { return &m_child; }
const ClassA* child() const { return &m_child; }
This way you can call non-const methods on ClassA when you have a non-const object.