I am training to my exam in c++ and I don't understand why the code display only print function of the base class (also after I debug the code) and never go to the print of derived class.
Can you explain me why in a simple way, and does there is some issue I can do in order to also display the print function of derived class only by edit a few line of code.
Let say the number that the program generate are: 1 67 0 69 0 0 58 78.
class A
{
int a;
public:
A(int x):a(x){}
void print() { cout << "a=" << a << ' '; }
};
class B:public A
{
int b;
public:
B(int x,int y) :A(x),b(y) {}
void print() { A::print(); cout << "b=" << b << ' '; }
};
int main(){
list<A*> lst;
for (int i = 0; i < 3; i++)
if(rand()%2)
lst.push_back(new A(rand() % 100));
else
lst.push_back(new B(rand() % 100,rand()%100));
for (list<A*>::iterator it = lst.begin(); it != lst.end(); it++)
(*it)->print();
}
You need to declare print() virtual in order for polymorphism to work.
Here is your example with suggested formatting improvements,
#include <iostream>
#include <list>
class A{
int a;
public:
A(int x):a(x){}
virtual void print() { std::cout << "a=" << a << ' '; }
};
class B:public A{
int b;
public:
B(int x,int y) :A(x),b(y) {}
void print() override { A::print(); std::cout << "b=" << b << ' '; }
};
int main(){
std::list<A*> lst;
for (int i = 0; i < 30; i++) {
if(rand()%2) {
lst.push_back(new A(rand() % 100));
} else {
lst.push_back(new B(rand() % 100,rand()%100));
}
}
for (std::list<A*>::iterator it = lst.begin(); it != lst.end(); it++) {
(*it)->print();
}
}
I increased the number of printed elements, because in these settings I wasn't getting a single b. This said:
You need to seed your code with srand if you don't want to get the same numbers over and over again (and you need to seed it only once per program).
If possible, you should use the new random number generation functionality available from C++11 on.
override is optional, but very encouraged, it clearly signals that the function was virtual and re-implemented.
Most importantly you need to free the memory you allocated with new (using delete), or better yet, use the approach in #TedLyngmo answer (smart pointers)
In order to make use of dynamic dispatch, you need to make A::print() virtual. You also need to make A's destructor virtual to be able to delete objects through the base class pointer.
Since you currently do not delete any objects (but instead leak all A's and Bs) I suggest that you make use of a smart pointer, std::unique_ptr<A>, that will clean up when the std::list is destroyed.
Example:
#include <iostream>
#include <list>
#include <memory> // std::unique_ptr
class A {
int a;
public:
A(int x) : a(x) {}
virtual ~A() = default; // virtual destructor
virtual void print() { std::cout << "a=" << a << ' '; }
};
class B : public A {
int b;
public:
B(int x, int y) : A(x), b(y) {}
void print() override {
A::print();
std::cout << "b=" << b << ' ';
}
};
int main() {
std::list<std::unique_ptr<A>> lst; // use of smart pointer
for(int i = 0; i < 30; i++) {
if(rand() % 2) {
lst.emplace_back(std::make_unique<A>(rand() % 100));
} else {
lst.emplace_back(std::make_unique<B>(rand() % 100, rand() % 100));
}
}
for(auto it = lst.begin(); it != lst.end(); it++) {
(*it)->print();
}
// Simpler loop: A range-based for loop:
// for(auto& ptr : lst) ptr->print();
}
Related
Haha, so I'm a little late to starting my homework and would enjoy having someone explain this to me, I read parts of my textbook so I understand the simple examples of base classes and derived classes but other than that I'm stumped. It doesn't seem to hard but I just need some help on where to start/look.
What is the output of the following C++ program?
#include <iostream>
#include <string>
using namespace std;
class baseClass {
public:
void print() const;
baseClass(string s = " ", int a = 0);
// Postcondition: str = s; x = a;
protected:
int x;
private:
string str;
};
class derivedClass : public baseClass {
public:
void print() const;
derivedClass(string s = "", int a = 0, int b = 0);
};
// Postcondition: str = s; x = a; y = b;private:int y;};
int main() {
baseClass baseObject("This is the base class", 2);
derivedClass derivedObject("DDDDDD", 3, 7);
baseObject.print();
derivedObject.print();
system("pause");
return 0;
}
void baseClass::print() const { cout << x << " " << str << endl; }
baseClass::baseClass(string s, int a) {
str = s;
x = a;
}
void derivedClass::print() const {
cout << "Derived class: " << y << endl;
baseClass::print();
}
derivedClass::derivedClass(string s, int a, int b)
: baseClass("Hello Base", a + b) {
y = b;
}
I haven't tried anything yet lol, just started my homework too late and it is due today and would love a quick explanation and help with the answer.
I know that dynamic_cast has a serious cost, but when I try the following codes, I get a bigger value almost every time from virtual function call loop. Do I know wrong until this time?
EDIT: The problem was that my compiler had been in debug mode. When I switched to release mode, virtual function call loop runs 5 to 7 times faster than dynamic_cast loop.
struct A {
virtual void foo() {}
};
struct B : public A {
virtual void foo() override {}
};
struct C : public B {
virtual void foo() override {}
};
int main()
{
vector<A *> vec;
for (int i = 0; i < 100000; ++i)
if (i % 2)
vec.push_back(new C());
else
vec.push_back(new B());
clock_t begin = clock();
for (auto iter : vec)
if (dynamic_cast<C*>(iter))
;
clock_t end = clock();
cout << (static_cast<double>(end) - begin) / CLOCKS_PER_SEC << endl;
begin = clock();
for (auto iter : vec)
iter->foo();
end = clock();
cout << (static_cast<double>(end) - begin) / CLOCKS_PER_SEC << endl;
return 0;
}
Since you are not doing anything with the result of the dynamic_cast in the lines
for (auto iter : vec)
if (dynamic_cast<C*>(iter))
;
the compiler might be optimizing away most of that code if not all of it.
If you do something useful with the result of the dynamic_cast, you might see a difference. You could try:
for (auto iter : vec)
{
if (C* cptr = dynamic_cast<C*>(iter))
{
cptr->foo();
}
if (B* bptr = dynamic_cast<B*>(iter))
{
bptr->foo();
}
}
That will most likely make a difference.
See http://ideone.com/BvqoqU for a sample run.
Do I know wrong until this time?
We probably can not tell from your code. The optimizer is clever, and it is some times quite challenging to 'defeat' or 'deceive' it.
In the following, I use 'assert()' to try to control the optimizer's enthusiasm. Also note that 'time(0)' is a fast function on Ubuntu 15.10. I believe the compiler does not yet know what the combination will do, and thus will not remove it, providing a more reliable/repeatable measurement.
I think I like these results better, and perhaps these indicate that dynamic cast is slower than virtual function invocation.
Environment:
on an older Dell, using Ubuntu 15.10, 64 bit, and -O3
~$ g++-5 --version
g++-5 (Ubuntu 5.2.1-23ubuntu1~15.10) 5.2.1 20151028
Results (dynamic cast followed by virtual funtion):
void T523_t::testStruct()
0.443445
0.184873
void T523_t::testClass()
252,495 us
184,961 us
FINI 2914399 us
Code:
#include <chrono>
// 'compressed' chrono access --------------vvvvvvv
typedef std::chrono::high_resolution_clock HRClk_t; // std-chrono-hi-res-clk
typedef HRClk_t::time_point Time_t; // std-chrono-hi-res-clk-time-point
typedef std::chrono::milliseconds MS_t; // std-chrono-milliseconds
typedef std::chrono::microseconds US_t; // std-chrono-microseconds
typedef std::chrono::nanoseconds NS_t; // std-chrono-nanoseconds
using namespace std::chrono_literals; // support suffixes like 100ms, 2s, 30us
#include <iostream>
#include <iomanip>
#include <vector>
#include <cassert>
// original ////////////////////////////////////////////////////////////////////
struct A {
virtual ~A() = default; // warning: ‘struct A’ has virtual functions and
// accessible non-virtual destructor [-Wnon-virtual-dtor]
virtual void foo() { assert(time(0)); }
};
struct B : public A {
virtual void foo() override { assert(time(0)); }
};
struct C : public B {
virtual void foo() override { assert(time(0)); }
};
// with class ////////////////////////////////////////////////////////////////////////////
// If your C++ code has no class ... why bother?
class A_t {
public:
virtual ~A_t() = default; // warning: ‘struct A’ has virtual functions and
// accessible non-virtual destructor [-Wnon-virtual-dtor]
virtual void foo() { assert(time(0)); }
};
class B_t : public A_t {
public:
virtual void foo() override { assert(time(0)); }
};
class C_t : public B_t {
public:
virtual void foo() override { assert(time(0)); }
};
class T523_t
{
public:
T523_t() = default;
~T523_t() = default;
int exec()
{
testStruct();
testClass();
return(0);
}
private: // methods
std::string digiComma(std::string s)
{ //vvvvv--sSize must be signed int of sufficient size
int32_t sSize = static_cast<int32_t>(s.size());
if (sSize > 3)
for (int32_t indx = (sSize - 3); indx > 0; indx -= 3)
s.insert(static_cast<size_t>(indx), 1, ',');
return(s);
}
void testStruct()
{
using std::vector;
using std::cout; using std::endl;
std::cout << "\n\n " << __PRETTY_FUNCTION__ << std::endl;
vector<A *> vec;
for (int i = 0; i < 10000000; ++i)
if (i % 2)
vec.push_back(new C());
else
vec.push_back(new B());
clock_t begin = clock();
int i=0;
for (auto iter : vec)
{
if(i % 2) (assert(dynamic_cast<C*>(iter))); // if (dynamic_cast<C*>(iter)) {};
else (assert(dynamic_cast<B*>(iter)));
}
clock_t end = clock();
cout << "\n " << std::setw(8)
<< ((static_cast<double>(end) - static_cast<double>(begin))
/ CLOCKS_PER_SEC) << endl; //^^^^^^^^^^^^^^^^^^^^^^^^^^
// warning: conversion to ‘double’ from ‘clock_t {aka long int}’ may alter its value [-Wconversion]
begin = clock();
for (auto iter : vec)
iter->foo();
end = clock();
cout << "\n " << std::setw(8)
<< ((static_cast<double>(end) - static_cast<double>(begin))
/ CLOCKS_PER_SEC) << endl; //^^^^^^^^^^^^^^^^^^^^^^^^^^
// warning: conversion to ‘double’ from ‘clock_t {aka long int}’ may alter its value [-Wconversion]
}
void testClass()
{
std::cout << "\n\n " << __PRETTY_FUNCTION__ << std::endl;
std::vector<A_t *> APtrVec;
for (int i = 0; i < 10000000; ++i)
{
if (i % 2) APtrVec.push_back(new C_t());
else APtrVec.push_back(new B_t());
}
{
Time_t start_us = HRClk_t::now();
int i = 0;
for (auto Aptr : APtrVec)
{
if(i % 2) assert(dynamic_cast<C_t*>(Aptr)); // check for nullptr
else assert(dynamic_cast<B_t*>(Aptr)); // check for nullptr
++i;
}
auto duration_us = std::chrono::duration_cast<US_t>(HRClk_t::now() - start_us);
std::cout << "\n " << std::setw(8)
<< digiComma(std::to_string(duration_us.count()))
<< " us" << std::endl;
}
{
Time_t start_us = HRClk_t::now();
for (auto Aptr : APtrVec) {
Aptr->foo();
}
auto duration_us = std::chrono::duration_cast<US_t>(HRClk_t::now() - start_us);
std::cout << "\n " << std::setw(8)
<< digiComma(std::to_string(duration_us.count()))
<< " us" << std::endl;
}
}
}; // class T523_t
int main(int argc, char* argv[])
{
std::cout << "\nargc: " << argc << std::endl;
for (int i = 0; i < argc; i += 1) std::cout << argv[i] << " ";
std::cout << std::endl;
setlocale(LC_ALL, "");
std::ios::sync_with_stdio(false);
{ time_t t0 = std::time(nullptr); while(t0 == time(nullptr)) { /**/ }; }
Time_t start_us = HRClk_t::now();
int retVal = -1;
{
T523_t t523;
retVal = t523.exec();
}
auto duration_us = std::chrono::duration_cast<US_t>(HRClk_t::now() - start_us);
std::cout << "\n FINI " << (std::to_string(duration_us.count()))
<< " us" << std::endl;
return(retVal);
}
update 2017-08-31
I suspect many of you will object to performing the dynamic cast without using the result. Here is one possible approach by replacing the for-auto loop in testClass() method:
for (auto Aptr : APtrVec)
{
if(i % 2) { C_t* c = dynamic_cast<C_t*>(Aptr); assert(c); c->foo(); }
else { B_t* b = dynamic_cast<B_t*>(Aptr); assert(b); b->foo(); }
++i;
}
With results
void T523_t::testStruct()
0.443445
0.184873
void T523_t::testClass()
322,431 us
191,285 us
FINI 4156941 us
end update
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
My first question is: I am having a lot of trouble figuring out why the Example class is being constructed greater than the others. Below is a short app using a Template counter to track how many times the constructor/destructor/copy constructor is called for each class. There are a total of three classes: Example, Deep, Child. Each has a copy constructor... ugh.
Also, my second question, is what would be the correct way to define the copy constructor for the Child class?
In the printStatus(), it displays:
COUNTERS::NEW_COUNTER = 60
COUNTERS::DELETE_COUNTER = 50
COUNTERS::CONSTRUCTOR_COUNTER = 90
COUNTERS::DESTRUCTOR_COUNTER = 80
Example count = 10
Deep count = 0
Child count = 0
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class COUNTERS
{
public:
static int NEW_COUNTER;
static int DELETE_COUNTER;
static int CONSTRUCTOR_COUNTER;
static int DESTRUCTOR_COUNTER;
};
int COUNTERS::NEW_COUNTER = 0;
int COUNTERS::DELETE_COUNTER = 0;
int COUNTERS::CONSTRUCTOR_COUNTER = 0;
int COUNTERS::DESTRUCTOR_COUNTER = 0;
/* template used for counting constructors/destructors to debug memory leaks */
template <typename T>
class Countable
{
static unsigned cs_count_;
public:
Countable() { ++cs_count_; }
Countable( Countable const& ) { ++cs_count_; }
virtual ~Countable() { --cs_count_;}
static unsigned count() { return cs_count_; }
};
template <typename T>
unsigned Countable<T>::cs_count_ = 0;
class Example : public Countable<Example>
{
public:
string a;
int b;
Example() {
COUNTERS::CONSTRUCTOR_COUNTER++;
a = "exampleString";
b = 5;
}
virtual ~Example() {
COUNTERS::DESTRUCTOR_COUNTER++;
}
// copy constructor
Example(const Example& e) {
COUNTERS::CONSTRUCTOR_COUNTER++;
this->a = e.a;
this->b = e.b;
}
};
class Deep : public Countable<Deep>
{
public:
int a;
string b;
Example* e;
Deep()
{
COUNTERS::CONSTRUCTOR_COUNTER++;
a = 3;
b = "deepString";
e = new Example();
COUNTERS::NEW_COUNTER++;
}
virtual ~Deep() {
if(e != NULL) {
delete e;
COUNTERS::DELETE_COUNTER++;
}
COUNTERS::DESTRUCTOR_COUNTER++;
}
// copy constructor
Deep(const Deep& x)
{
COUNTERS::CONSTRUCTOR_COUNTER++;
this->a = x.a;
this->b = x.b;
this->e = new Example();
COUNTERS::NEW_COUNTER++;
this->e->a = x.e->a;
this->e->b = x.e->b;
};
};
class Child : public Countable<Child>
{
public:
Deep d;
string name;
int age;
Example* e;
vector<Example> list;
vector<Deep> deep_list;
void init()
{
Deep* var = new Deep(); COUNTERS::NEW_COUNTER++;
deep_list.push_back(*var);
delete var; COUNTERS::DELETE_COUNTER++;
}
Child() {
COUNTERS::CONSTRUCTOR_COUNTER++;
name = "a";
age = 10;
d.a = 1;
d.b = "deep";
d.e = NULL;
e = new Example();
COUNTERS::NEW_COUNTER++;
list.push_back(*e);
init();
}
virtual ~Child() {
COUNTERS::DESTRUCTOR_COUNTER++;
if(e != NULL) {
delete e;
COUNTERS::DELETE_COUNTER++;
}
}
// copy constructor
Child(const Child& c)
{
}
};
void myChildFunction(){
Child* c = new Child();
COUNTERS::NEW_COUNTER++;
delete c;
COUNTERS::DELETE_COUNTER++;
}
void printStatus(){
cout << "COUNTERS::NEW_COUNTER = " << COUNTERS::NEW_COUNTER << endl;
cout << "COUNTERS::DELETE_COUNTER = " << COUNTERS::DELETE_COUNTER << endl;
cout << "COUNTERS::CONSTRUCTOR_COUNTER = " << COUNTERS::CONSTRUCTOR_COUNTER << endl;
cout << "COUNTERS::DESTRUCTOR_COUNTER = " << COUNTERS::DESTRUCTOR_COUNTER << endl;
cout << "Example count = " << Example::count() << endl;
cout << "Deep count = " << Deep::count() << endl;
cout << "Child count = " << Child::count() << endl;
}
int main()
{
for(unsigned int i=0 ; i < 10; i++)
myChildFunction();
printStatus();
return 0;
}
You are missing out on deleting some Example objects because of this line:
d.e = NULL;
in Child::Child().
You are allocating memory for e in the constructor of Deep. After executing the above line, that memory is leaked.
You can resolve that problem by:
Removing that line (or commenting it out),
Deleting d.e before making it NULL, or
Doing something else that prevents the memory leak.
Update, in response to comment
Copy constructor for Child:
Child(const Child& c) : d(c.d),
name(c.name),
age(c.age),
e(new Example(*c.e)),
list(c.list),
deep_list(c.deep_list)
{
COUNTERS::DESTRUCTOR_COUNTER++; // This is for Child
COUNTERS::NEW_COUNTER++; // This is for new Example
}
I removed all information that cluttered your code.
When using templates, constructors and copy constructors NEED the following: Example < eltType >(void);
in the class definition. All objects that inherit from Countables are known as derived classes. They also may call a derived class a child, and the class in which it is derived from is called the parent. I added the COPY_CONSTRUCTOR_COUNT to add clarification to the data which is being presented on the console/command prompt. Usually when trying to preform a task, large or small, doing it incrementally and by providing methods, for each task, saves you time and a headache. I removed the new_count and delete_count from the equation, because I felt that it was not needed.
You will notice that I added : Countable( * ((Countable < eltType > *)&e))
This is a requirement when designing a program that involves inheritance, which introduces the
topic of Polymorphism :D
What that bit of code does is that it gets a pointer of a Countable, which will point to the address of object e, which then allows access to all super classes of this class, but not including e's class.
NOTE: Since e is a derived class of Countable, this is valid statement.
For you second question, all of your data members are public, you can use an iterator to copy your data stored in you vectors.
As a concern from one programmer to another, I hope your code in practice is well documented, and all methods declared in your class are defined in a .cpp file.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class COUNTERS
{
public:
static int NEW_COUNTER;
static int DELETE_COUNTER;
static int CONSTRUCTOR_COUNTER;
static int DESTRUCTOR_COUNTER;
static int COPY_CONSTRUCTOR_COUNTER;
};
int COUNTERS::NEW_COUNTER = 0;
int COUNTERS::DELETE_COUNTER = 0;
int COUNTERS::CONSTRUCTOR_COUNTER = 0;
int COUNTERS::DESTRUCTOR_COUNTER = 0;
int COUNTERS::COPY_CONSTRUCTOR_COUNTER = 0;
/* template used for counting constructors/destructors to debug memory leaks */
template <typename T>
class Countable
{
public:
Countable<T>()
{
incrementObjectCount();
};
Countable<T>(Countable const&)
{
incrementObjectCount();
};
virtual ~Countable()
{
decrementObjectCount();
};
static unsigned count()
{
return cs_count_;
};
protected:
static unsigned cs_count_;
////////////////////////////////////ADDED////////////////////////////////////
protected:
void incrementObjectCount(void){ ++cs_count_; };
void decrementObjectCount(void){ --cs_count_; };
void incrementDeconstructorCounter(void){ ++COUNTERS::DESTRUCTOR_COUNTER; };
/////////////////////////////////////ADDED////////////////////////////////////
};
template <typename T>
unsigned Countable<T>::cs_count_ = 0;
class Example : public Countable<Example>
{
public:
Example() : Countable<Example>()
{
COUNTERS::CONSTRUCTOR_COUNTER++;
}
virtual ~Example()
{
incrementDeconstructorCounter();
}
// copy constructor
Example(const Example& e) : Countable<Example>(*((Countable<Example>*)&e))
{
// COUNTERS::CONSTRUCTOR_COUNTER++; This is copy constructor, you addmitted this from "Child" class CCstr
++COUNTERS::COPY_CONSTRUCTOR_COUNTER; // For even more information added this
}
};
class Deep : public Countable<Deep>
{
public:
Deep() : Countable<Deep>()
{
COUNTERS::CONSTRUCTOR_COUNTER++;
}
virtual ~Deep()
{
COUNTERS::DESTRUCTOR_COUNTER++;
}
// copy constructor
Deep(const Deep& x) : Countable<Deep>(*((Countable<Deep>*)&x))
{
//COUNTERS::CONSTRUCTOR_COUNTER++;
++COUNTERS::COPY_CONSTRUCTOR_COUNTER; // For even more information added this
};
};
class Child : public Countable<Child>
{
public:
vector<Example> list;
vector<Deep> deep_list;
void init()
{
deep_list.push_back(Deep());
list.push_back(Example());
}
Child() : Countable<Child>()
{
COUNTERS::CONSTRUCTOR_COUNTER++;
init();
}
virtual ~Child()
{
COUNTERS::DESTRUCTOR_COUNTER++;
}
// copy constructor
Child(const Child& c) : Countable<Child>(*((Countable<Child>*)&c))
{
++COUNTERS::COPY_CONSTRUCTOR_COUNTER; // For even more information added this
}
};
void myChildFunction(){
Child* c = new Child();
//COUNTERS::NEW_COUNTER++;not needed
delete c;
//COUNTERS::DELETE_COUNTER++; not need
}
void printStatus(){
cout << "COUNTERS::NEW_COUNTER = " << COUNTERS::NEW_COUNTER << endl;
cout << "COUNTERS::DELETE_COUNTER = " << COUNTERS::DELETE_COUNTER << endl;
cout << "COUNTERS::CONSTRUCTOR_COUNTER = " << COUNTERS::CONSTRUCTOR_COUNTER << endl;
cout << "COUNTERS::DESTRUCTOR_COUNTER = " << COUNTERS::DESTRUCTOR_COUNTER << endl;
cout << "COUNTERS::COPY_CONSTRUCTOR_COUNTER = " << COUNTERS::COPY_CONSTRUCTOR_COUNTER << endl;
cout << "Example count = " << Example::count() << endl;
cout << "Deep count = " << Deep::count() << endl;
cout << "Child count = " << Child::count() << endl;
}
int main()
{
for (unsigned int i = 0; i < 10; i++)
myChildFunction();
printStatus();
system("pause");
return 0;
}
This question already has answers here:
When should static_cast, dynamic_cast, const_cast, and reinterpret_cast be used?
(11 answers)
Closed 9 years ago.
What would be a genuinely-acceptable example of usage for a derived cast? I have always thought they are only used when implementing "hacks" but if this is not the case, could someone give an acceptable example of when to use one?
#user997112
[edit at bottom]
Hello. Below we use a collection of random polymorphic pointers with common ancestor
through the common interface.
Additional work is done with one of the particular derived classes
we need dynamic_cast or typeid to know this ....
main function has the call
then class declarations
then the dynamic cast is at end
delete of objects created with new is not shown
#include <iostream>
#include <algorithm>
#include <random>
#include <exception>
using namespace std;
int dynamic_test();
int main()
{
cout << "Hello world!" << endl;
dynamic_test();
return 0;
}
............
class basex {
public:
virtual ~basex() {};
virtual void work() const = 0;
};
class next1x : public basex {
public:
void work() const override {cout << "1";/*secret*/}
};
class next2x : public basex {
public:
void work() const override {cout << "2";/*secret*/}
};
class next3x : public basex {
public:
void work() const override {cout << "3";/*secret*/}
};
std::vector<basex *> secret_class_picker()
{
//pick classes with common base at random
std::random_device rd;
std::uniform_int_distribution<int> ud(1,3);
std::mt19937 mt(rd());
std::vector<int> random_v;
for (int i = 0; i < 22; ++i)
random_v.push_back( ud(mt) );
cout << "Random" << endl;
for ( auto bq : random_v) //inspecting for human reader
cout << bq << " ";
std::vector<basex *> v;
basex * bptr;
for (auto bq : random_v) {
switch(bq)
{
default: throw std::exception(); break;
case 1: bptr = new next1x; break;
case 2: bptr = new next2x; break;
case 3: bptr = new next3x; break;
}
v.push_back(bptr);
}
cout << "Objects Created " << v.size() << endl;
return v;
}
//this function demands a more derived class
int special_work(const next3x *)
{
//elided
cout <<"[!]";
return 0;
}
int dynamic_test()
{
std::vector<basex *> v = secret_class_picker();//delete these pointer later
cout <<"Working with random polymorphic pointers"<<endl;
for (const auto bq : v)
{
bq->work();//polymorphic
next3x * ptr = dynamic_cast<next3x *>(bq);
if (nullptr != ptr) special_work(ptr); //reserved for particular type
}
return 0;
}
...................... alternative
int dynamic_static_typeid()
{
std::vector<basex *> v = secret_class_picker();
cout <<"Working with random polymorphic pointers"<<endl;
int k(0);
for (const auto bq : v)
{
bool flipflop = (k % 2) == 0;
bq->work();//polymorphic
//cout << "[*]"<< typeid(*bq).name();//dereference
if (flipflop) {
next3x * dc_ptr = dynamic_cast<next3x *>(bq);//not constant time in general
if (nullptr != dc_ptr) {
special_work(dc_ptr); //reserved for particular type
++k;
}
}
else {
if (typeid(next3x) == typeid(*bq)){//constant time
auto sc_ptr = static_cast<next3x *>(bq);//constant time
special_work(sc_ptr);
++k; cout <<"[sc]";
}
}
cout << endl;
}
return 0;
}
I have a vec_A that stores instances of class A as: vec_A.push_back(A());
I want to remove some elements in the vector at a later stage and have two questions: a) The element is deleted as: vec_A.erase(iterator) Is there any additional code I need to add to make sure that there is no memory leak? .
b) Assume that condition if(num <5) is if num is among a specific numberList. Given this, is there a better way to delete the elements of a vector than what I am illustrating below?
#include<vector>
#include<stdio.h>
#include<iostream>
class A {
public:
int getNumber();
A(int val);
~A(){};
private:
int num;
};
A::A(int val){
num = val;
};
int A::getNumber(){
return num;
};
int main(){
int i =0;
int num;
std::vector<A> vec_A;
std::vector<A>::iterator iter;
for ( i = 0; i < 10; i++){
vec_A.push_back(A(i));
}
iter = vec_A.begin();
while(iter != vec_A.end()){
std::cout << "\n --------------------------";
std::cout << "\n Size before erase =" << vec_A.size();
num = iter->getNumber() ;
std::cout << "\n num = "<<num;
if (num < 5){
vec_A.erase(iter);
}
else{
iter++;
}
std::cout << "\n size after erase =" << vec_A.size();
}
std::cout << "\nPress RETURN to continue...";
std::cin.get();
return 0;
}
a) The element is deleted as:
vec_A.erase(iterator) Is there any
additional code I need to add to make
sure that there is no memory leak? .
Yes, that's all you need to do. There will be no memory leak. Since you didn't allocate yoour object on heap, when you did vec_A.push_back(A()) a new object is copied into the vector. When you do erase, vector will take care of deleting the elements.
Assume that condition if(num <5) is if
num is among a specific numberList.
Given this, is there a better way to
delete the elements of a vector than
what I am illustrating below?
Yes, you can remove/erase idiom. This is an example:
class A
{
public:
A(int n) : m_n(n)
{
}
int get() const
{
return m_n;
}
private:
int m_n;
};
bool lessThan9(const A& a)
{
return a.get() < 9;
}
//Or if you want for a generic number
struct Remover : public std::binary_function<A,int,bool>
{
public:
bool operator()(const A& a, int n)const
{
return a.get() < n;
}
};
int main()
{
std::vector<A> a;
a.push_back(A(10));
a.push_back(A(8));
a.push_back(A(11));
a.push_back(A(3));
a.erase(std::remove_if(a.begin(), a.end(), lessThan9), a.end());
//Using the user-defined functor
a.erase(std::remove_if(a.begin(), a.end(), std::bind2nd(Remover(), 9)), a.end());
return 0;
}
1) Resource handling is done by the class itself. The destructor of a class is responsible to ensure that there is no memory leak.
2) Removing elements from a vector is best done back-to-front:
for (std::vector<A>::reverse_iterator it = vec_A.rend(); it != vec_A.rbegin(); --it)
{
if (it->getNumber() < 5) {vec_A.erase(it.base());}
}