I want to move the data of a virtual base class object before it is cleared, but I don't know how. Can anyone help?
I prefer not to copy because it is used in a program that cares about performance.
#include <iostream>
#include <vector>
class A {
public:
void clear() {
handleClear();
}
virtual int size() = 0;
protected:
virtual void handleClear() = 0;
};
class B : public A {
public:
int size() override {
return buffer_.size();
}
void handleClear() override {
buffer_.clear();
}
std::vector<int> buffer_;
};
void write(A& a) {
std::cout << a.size() << std::endl;
// How can I move out the data before a.clear() called.
// A new_a = std::move(a);
std::cout << a.size() << std::endl;
a.clear();
}
int main()
{
B b;
b.buffer_ = {1, 2};
write(b);
}
Related
Assume the snippet below. How can I make this compiling/working? I do not want to move print to the String/Float class, because in my real world situation this function is combining a lot of data.
So basically I want a pointer/member to "any type (in this case string/float)" then use it, and call dynamically something else (in this case print)?
I assume that this does not work (among others) because it cannot determine at compile time which type T of ptr will have at compile time.
What is the general pattern to solve such kind of problems?
#include <iostream>
template<typename T>
class AbstractClass {
virtual T getValue()=0;
};
class StringClass : public AbstractClass<std::string> {
std::string getValue() override {
return "A";
}
};
class FloatClass : public AbstractClass<float> {
float getValue() override {
return 1;
}
};
class Processor {
public:
AbstractClass<T>* ptr;
void doIt() {
ptr=new StringClass();
print(ptr->getValue());
delete ptr;
ptr=new FloatClass();
print(ptr->getValue());
delete ptr;
}
void print(std::string i) {
std::cout << "String "<<i<<std::endl;
}
void print(float i) {
std::cout << "Float "<<i<<std::endl;
}
}
int main() {
Processor a;
a.doIt();
}
If you want an object that's 'one of' a given set of types, you can use std::variant<Ts...>. Mathematically, it represents discriminated/tagged union. This way, you don't need a pointer, neither a base class. Example:
#include <iostream>
#include <variant>
class StringClass {
std::string getValue() override {
return "A";
}
};
class FloatClass {
float getValue() override {
return 1;
}
};
using ClassWithGetValue = std::variant<StringClass, FloatClass>;
class Processor {
public:
ClassWithGetValue v;
void doIt() {
v = StringClass();
std::visit([&](auto&& v1) {
print(v1.getValue());
});
v = FloatClass();
std::visit([&](auto&& v1) {
print(v1.getValue());
});
}
void print(std::string i) {
std::cout << "String "<<i<<std::endl;
}
void print(float i) {
std::cout << "Float "<<i<<std::endl;
}
}
int main() {
Processor a;
a.doIt();
}
In C ++, I first encountered function pointers.
I tried to use this to make it similar to Action and Delegate in C #.
However, when declaring a function pointer, it is necessary to specify the type of the class in which the function exists.
ex) void (A :: * F) ();
Can I use a function pointer that can store a member function of any class?
In general, function pointers are used as shown in the code below.
class A {
public:
void AF() { cout << "A::F" << endl; }
};
class B {
public:
void(A::*BF)();
};
int main()
{
A a;
B b;
b.BF = &A::AF;
(a.*b.BF)();
return 0;
}
I want to use it like the code below.
is this possible?
Or is there something else to replace the function pointer?
class A {
public:
void AF() { cout << "A::F" << endl; }
};
class B {
public:
void(* BF)();
};
int main()
{
A a;
B b;
b.BF = a.AF;
return 0;
}
I solved the question through the answer.
Thanks!
#include <functional>
#include <iostream>
class A {
public:
void AF() { std::cout << "A::F" << std::endl; }
};
class C {
public:
void CF() { std::cout << "C::F" << std::endl; }
};
class B {
public:
B(){}
std::function<void()> BF;
};
int main() {
A a;
C c;
B b;
b.BF = std::bind(&A::AF, &a);
b.BF();
b.BF = std::bind(&C::CF, &c);
b.BF();
int i;
std::cin >> i;
return 0;
}
What you want to do is probably something like this. You can use std::function to hold a pointer to a member function bound to a specific instance.
#include <functional>
#include <iostream>
class A {
public:
void AF() { std::cout << "A::F" << std::endl; }
};
class B {
public:
B(const std::function<void()>& bf) : BF(bf) {}
std::function<void()> BF;
};
int main() {
A a;
B b1(std::bind(&A::AF, &a)); // using std::bind
B b2([&a] { a.AF(); }); // using a lambda
b1.BF();
b2.BF();
return 0;
}
Here's a C# style implementation of the accepted answer, It is memory efficient and flexible as you can construct and delegate at different points of execution which a C# developer might expect to do:
#include <iostream>
#include <functional>
using namespace std;
class A {
public:
void AF() { cout << "A::F" << endl; }
void BF() { cout << "B::F" << endl; }
};
class B {
public:
std::function<void()> Delegate;
};
int main() {
A a;
B b;
b.Delegate = std::bind(&A::AF, &a);
b.Delegate();
b.Delegate = [&a] { a.BF(); };
b.Delegate();
return 0;
}
I'm looking for a design pattern which can store vector of pointers and can remove the vector of pointers based on the demand.
This is my existing code path.
### implementation.h
class A {
A() {}
private:
void AggregateMetrics();
void FlushMetrics();
X* x_;
Y* y_;
};
class X {
public:
void CreateFiles(vector<B*> *objects, string path);
};
class B {
B() {
m_ = 0, n_ = 0;
}
private:
int m_, n_;
};
### implementation.cpp
void A::A() {
x_ = new X();
y_ = new Y();
}
void A::AggregateMetrics() {
}
void A::FlushMetrics () {
vector<B*> objects;
x_->CreateFiles(&objects, path);
// In my new code, we are going to move the above two lines
// to AggregateMetrics() and i need to find a way to store
// the vector<B*>objects;
y_->Flush(objects);
return;
}
void X::CreateFiles(vector<B*> *objects, string path) {
CHECK(objects.empty());
for (int i = 0; i < 10; i++) {
objects->push_back(new B());
}
}
Here is my new code:
### implementation.h
class A {
A() {}
private:
void AggregateMetrics();
void FlushMetrics();
X* x_;
Y* y_;
};
class X {
public:
void CreateFiles(vector<B*> *objects, string path);
};
class B {
B() {
m_ = 0, n_ = 0;
}
private:
int m_, n_;
};
class PointerManager {
public:
PointerManager() {}
void SetPointers(vector<B*>& objects);
vector<B*> GetPointers();
private:
vector<B*>objects_;
};
### implementation.cpp
PointerManager::SetPointers(vector<B*>& objects) {
objects_ = objects;
}
vector<B*> PointerManager::GetPointers() {
return objects_;
}
void A::A() {
x = new X();
y = new Y();
mgr_ = new PointerManager();
}
void A::AggregateMetrics() {
vector<B*> objects;
x->CreateFiles(&objects, path);
mgr_->SetPointers(objects);
}
void A::FlushMetrics () {
auto objects = mgr_->GetPointers();
y->Flush(objects);
return;
}
void X::CreateFiles(vector<B*> *objects, string path) {
CHECK(objects.empty());
for (;;) {
objects->push_back(new B());
}
}
I'm basically creating a new class called PointerManager which can hold these pointers after the creation and can return when needed. What would be the ideal design here? Can you guys suggest a design pattern?
I suggest using smart pointer and store them into a container to avoid any memory leak.
Here's the version of your design using smart pointer
implementation.hpp :
#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <cassert>
class B {
public:
B() {
m_ = 0, n_ = 0;
}
private:
int m_, n_;
};
class Y{
public:
Y(){}
~Y(){}
void Flush(std::vector<std::unique_ptr<B>>& objects);
};
class X {
public:
void CreateFiles(std::vector<std::unique_ptr<B>> &objects, std::string path);
};
class PointerManager {
public:
PointerManager() {}
void InsertPointer(std::unique_ptr<B> &object);
void SetPointers(std::vector<std::unique_ptr<B>> &objects);
std::vector<std::unique_ptr<B>> &GetPointers();
private:
std::vector<std::unique_ptr<B>> objects_;
};
class A {
public:
A();
void AggregateMetrics();
void FlushMetrics();
private:
X* x_;
Y* y_;
PointerManager* mgr_;
};
implementation.cpp
#include "implementation.hpp"
void Y::Flush(std::vector<std::unique_ptr<B>>& objects){
for(int i =0;i<objects.size();i++){
objects[i].release();
}
}
void X::CreateFiles(std::vector<std::unique_ptr<B>> &objects, std::string path) {
assert(objects.empty());
for (int i = 0; i < 5;i++) {
std::cout << "for loop in CreatesFiles " << std::endl;
objects.emplace_back(new B);
}
}
void PointerManager::InsertPointer(std::unique_ptr<B> &object) {
std::cout << "InsertPointer " << std::endl;
objects_.push_back(std::move(object)); // object now belongs to PointerManager
}
void PointerManager::SetPointers(std::vector<std::unique_ptr<B>> &objects){
for(int i=0;i<objects.size();i++){
this->InsertPointer(objects[i]);
}
}
std::vector<std::unique_ptr<B>>& PointerManager::GetPointers() {
std::cout << "Get Pointers" << std::endl;
return objects_;
}
A::A() {
x_ = new X();
y_ = new Y();
mgr_ = new PointerManager();
}
void A::AggregateMetrics() {
std::cout << "Aggregate Metrics " << std::endl;
std::string path = ".";
std::vector<std::unique_ptr<B>> objects;
x_->CreateFiles(objects, path);
mgr_->SetPointers(objects);
}
void A::FlushMetrics () {
std::cout << "Flush Metrics " << std::endl;
y_->Flush(mgr_->GetPointers());
return;
}
This run fine with CLANG 3.4.2 and g++ 4.9.3 using -std=c++11 flag.
What you are basically asking is: "how do I implement my own memory management using raw pointers?"
And the answer to that is: you don't.
Modern day C++ offers concepts such as smart pointers or unique/shared pointers that take a lot of that "management" burden from the shoulders of your application code.
So the real answer here is: step back, and learn how to use C++ with all the means that are available in 2017; instead of writing code that would have been written like that 15, 20 years ago.
This is the example code I have:
#include <iostream>
#include <vector>
#include <string>
class Animal {
};
class Rabbit : public Animal {
};
class Caller {
public:
virtual void call(Animal* a) {
std::cout << "Caller calls animal" << std::endl;
}
virtual void call(Rabbit* r) {
std::cout << "Caller calls rabbit" << std::endl;
}
};
int main(int argc, char** argv) {
std::vector<Animal*> v;
Caller c;
auto a = new Animal();
auto r = new Rabbit();
v.push_back(a);
v.push_back(r);
for(auto elem : v) {
c.call(elem);
}
return 0;
}
The output of this code can be found here
http://ideone.com/I29g3A
and it outputs:
Caller calls animal
Caller calls animal
I'm wondering, without casting a specific element to Rabbit*, is there a way to get call(Rabbit *r) method to get called?
Sure, e.g., by jumping through a suitable visitor in your system of polymorphic classes. I think you'll need to use two names instead of call(), however. I used pubCall() and call().
#include <iostream>
#include <vector>
#include <string>
class Visitor;
class Animal {
public:
virtual void visit(Visitor&);
};
class Rabbit : public Animal {
void visit(Visitor&);
};
class Visitor
{
public:
virtual void call(Animal* a) = 0;
virtual void call(Rabbit* r) = 0;
};
void Animal::visit(Visitor& v) {
v.call(this);
}
void Rabbit::visit(Visitor& v) {
v.call(this);
}
class Caller
: Visitor {
public:
void pubCall(Animal* a) { a->visit(*this); }
private:
virtual void call(Animal* a) {
std::cout << "Caller calls animal" << std::endl;
}
virtual void call(Rabbit* r) {
std::cout << "Caller calls rabbit" << std::endl;
}
};
int main(int argc, char** argv) {
std::vector<Animal*> v;
Caller c;
auto a = new Animal();
auto r = new Rabbit();
v.push_back(a);
v.push_back(r);
for(auto elem : v) {
c.pubCall(elem);
}
return 0;
}
Can someone please explain why i->value() and (i + 1)->value() prints 1 and 3 not 1 and 4 like x[0]->value() << x[1]->value()
#include <iostream>
#include <vector>
class A
{
public:
A(int n = 0) : m_n(n) { }
public:
virtual int value() const { return m_n; }
virtual ~A() { }
protected:
int m_n;
};
class B
: public A
{
public:
B(int n = 0) : A(n) { }
public:
virtual int value() const { return m_n + 1; }
};
int main()
{
const A a(1); //a.m_n=1
const B b(3); //b.m_n=3
const A *x[2] = { &a, &b };
typedef std::vector<A> V;
V y;
y.push_back(a);
y.push_back(b);
V::const_iterator i = y.begin();
std::cout << x[0]->value() << x[1]->value()
<< i->value() << (i + 1)->value() << std::endl;
return 0;
}
Thank you
y.push_back(b); creates an instance of A which is a copy of the A subobject in b, and pushes that onto the vector. There are no instances of B on the vector, nor could there be, so B::value() is not called. Read about object slicing
void push_back (const value_type& val);
will create an A copy of val if the vector is defined as std::vector<A> V.
You see here so called slicing problem.
This is why you should use
std::vector<A*> V
or
std::vector<shared_ptr<A> > V