How to swap 2 different objects of an object array in C++? - c++

I'm trying to write a Swap function to swap 2 different types of objects of an array in C++. How can I do that? (I prefer using pointer to solve this problem)
I've tried to use template classes to swap 2 objects because the types of object are different from others and when looping through the array, I don't know which objects that one element belongs to.
I have 3 classes (Object_A, Object_B and Object_C) as below:
class Object_A : public base_class
{
private:
int workingTime;
int relaxTime;
float salary;
public:
Object_A();
virtual ~Object_A();
float Cal_Salary();
int getWorkingTime() const;
void setWorkingTime(int workingTime);
int getRelaxTime() const;
void setRelaxTime(int relaxTime);
float getSalary() const;
void setSalary(float salary);
};
class Object_B : public base_class
{
private:
float income;
public:
Officer();
virtual ~Officer();
float getIncome() const;
void setIncome(float income);
};
class Object_C : public base_class
{
private:
std::string role;
float roleCoef;
float bonus;
public:
Manager();
virtual ~Manager();
float Cal_Bonus();
const std::string& getRole() const;
void setRole(const std::string& role);
float getRoleCoef() const;
void setRoleCoef(float roleCoef);
float getBonus() const;
void setBonus(float bonus);
};
// I tried to write SwapValues func
template<class T, class U>
void SwapValues(T* a, U* b)
{
T temp = a;
a = b;
b = temp;
}
I have an array with base_class type to store some elements of three objects above (Object_A, Object_B and Object_C).
However when I want to swap one element of Object_A to one of Object_C with SwapValues() func, it doesn't work!
Thanks a lot for your help.

EDIT: Re-reading your question, the reason why your pointerswap doesn't work is because you are not passing the pointers as reference. If you insist on calling the function SwapValues, you can implement it like this:
class base_class {
// ...
friend void SwapValues(base_class*& a, base_class*& b) {
::std::swap(a,b);
}
};
Observe that SwapValues is still free function, not a member function.
You should always use ::std::swap as it sometimes offers efficient alternatives:
::std::swap(*a,*b);
You can also implement a member function in your class if you want to customise how swap works. For instance, your members can be swapped efficiently, as they are either POD or ::std::string which has a constant-time swap.

I think you should try
void SwapValues(T* a, U* b)
{
T* temp = a;
a = b;
b = temp;
}

Since your array consists of pointers (base_class* elements), you don't need your own swap function. You can just assign such pointers normally, and thus you can just use std::swap.

Related

Correct way to declare an Array member in a class

I have a class that looks like this
class StatisticsQuantiles : public StatisticsMC
{
public:
StatisticsQuantiles(double p_, unsigned long NumberOfPaths);
virtual void DumpOneResult(double result);
virtual std::vector<std::vector<double>> GetResultsSoFar() const;
virtual StatisticsMC* clone() const;
private:
std::vector<double> ResultList;
double p;
unsigned long PathsDone;
};
Currently it has a vector ResultList which I populate with values in my class when a function is called with a value like so:
void StatisticsQuantiles::DumpOneResult(double result)
{
ResultList.push_back(result);
PathsDone++;
}
Now I know that I will fill this vector with exactly NumberOfPaths many values, so I would like to use an array of a fixed size instead. How do I go about getting an array as a member of this class with size NumberOfPaths? I'm trying to do something like this which doesn't work of course but you get the idea:
class StatisticsQuantiles : public StatisticsMC
{
public:
StatisticsQuantiles(double p_, const unsigned long NumberOfPaths);
virtual void DumpOneResult(double result);
virtual std::vector<std::vector<double>> GetResultsSoFar() const;
virtual StatisticsMC* clone() const;
private:
std::array<double, NumberOfPaths> ResultList;
double p;
unsigned long PathsDone;
};
the size of std::array must be known at compile time, which is not the case here.
So std::vector is your option I believe.
If you are worried about the efficiency of push_back re-sizing, you can reserve the memory in your constructor.
ResultList.reserve(NumberOfPaths);
push_back then won't re-size unless you insert more than NumberOfPaths elements. So you don't have the un-necessary resizing.

How can I access member functions of STL classes inside derived classes that aren't in the base class? (detailed explanation in body)

Right now I have a base class, class Base{}, with two classes deriving from it, BFS{} and DFS{}. BFS has queue, and DFS has stack, so they both have a member called "nodes", but the type is their respective std::queue and std::stack. My search function takes in a pointer to base class as its parameter so that it can accept both derived classes, and runs the search by pushing and popping from the member classes inside the derived classes (as per the usual DFS BFS algorithms). The issue is, since I passed in my base class as the parameter, whenever I try to call push or pop on the member stack/queue called "nodes" from the derived classes, it always says that the push/pop cannot be done because there is no member inside the base class called "nodes". How am I supposed to make this work?
Also, this setup is a requirement of the assignment I am doing and I just can't figure out how this is supposed to work, any help is appreciated.
Thanks!
class Base {
public:
virtual void push(uint64_t roomID, float intensity, int distance) = 0;
virtual Node pop(void) = 0;
virtual int size(void) = 0;
};
class Breadth : public Base {
public:
std::queue<std::pair<uint64_t, int>> U;
void push(uint64_t roomID, float intensity, int distance) { std::pair<uint64_t, int> p(roomID, distance); U.push(p); }
Node pop() { Node rr; rr.ID = U.front().first; rr.distance = U.front().second; U.pop(); return rr; }
int size() { return U.size(); }
};
class Depth : public Base {
public:
std::stack<std::pair<uint64_t, int>> U;
void push(uint64_t roomID, float intensity, int distance) { std::pair<uint64_t, int> p(roomID, distance); U.push(p); }
UnexploredRoom pop() { U.pop(); }
int size() { U.size(); }
};
void robotSearch::searchLoop(Base* search, Discovered* D, uint64_t roomID)
{
Node room;
room.ID = roomID;
room.distance = 0;
search->U.push(room); //problem here, compiler wont let me push U
...
}
To implement custom behaviour through a pointer to a base class, you need to use virtual functions. Another approach would be to use generic code with templates.
Example:
class Base {
public:
virtual ~Base() {}
virtual void push(int i) = 0;
virtual int pop() = 0;
};
class DFS : public Base{
public:
virtual void push(int i) override { /*...*/ }
virtual int pop() override { /*...*/ return {}; }
};
class BFS : public Base {
public:
virtual void push(int i) override { /*...*/ }
virtual int pop() override { /*...*/ return {}; }
};
Right now, you have some virtual methods push and pop, but for some reason, you don't use them and instead try to access a member of the derived classes instead. You seem to have copied code from the answer by Ayjay but not applied it correctly.
That member U should really not be exposed like this, that is, it should be private, and you should use your class methods to manipulate it.
Therefore, you wouldn't write
search->U.push(room);
even if it was legal here (which it isn't, as the base class does not have anything named like that).
Instead, you go with
search->push(room);
Note that I omitted the other arguments that this takes, of course you also have to provide values for your intensity and distance arguments.
Doing so will call the appropriate method, that is either Breadth::push or Depth::push, which then will access the corresponding member of the respective class.
By the way, for reasons of control, you should use the override keyword as Ayjay did, and also, you should give a member a more descriptive name that U.

Workaround for virtual static function functionality

Let's say I have a class:
class StateVector {
protected:
float* _v;
public:
StateVector():_v(new float[size()]) {}
virtual ~StateVector() { delete [] _v; }
virtual size_t size() = 0;
// ...
};
class PositionState : public StateVector {
public:
size_t size() { return 3; }
float* x() { return _v; }
};
class MovingState : public PositionState {
public:
size_t size() { return PositionState::size() + 3; }
float* v() { return _v + PositionState::size(); }
};
The intent here is to allow derived classes to specify the size of the state vector by overriding size(). (This information needs to be available to the constructor of StateVector, the base class which owns the underlying array).
However, this is less than ideal for a few reasons:
First, in this implementation, size() must/will be the same for all instances of a class. But in this factoring, there is nothing that prevents different instances of the same class from having different opinions about size().
Second, other classes need to generate an instance in order to query the appropriate size:
template <typename State>
class StateTransition {
Matrix<float> _m;
// constructor for Matrix takes #rows, #cols
StateTransition():_m(State().size(), State().size()) {}
// ...
};
This is silly, because for all States, size() will be the same. In this case, size() might be quite large, and in the constructor for StateTransition will (by constructing two States) allocate two arrays of that size and then immediately throw them away!
Finally, it is expected that each derived class will carry a superset of its base's state, so size() should never be smaller for base classes than for derived classes– but since we can't traverse the inheritance tree, I don't know of a way to enforce this programmatically. This is a secondary concern, but it would be nice if there were a clean way to handle it.
It would make the most sense to be able to write:
class StateVector {
float* _v;
StateVector:_v(new float[size()]) {}
virtual static size_t size() = 0;
};
class PositionState {
static size_t size() { return 3; }
// ...
};
// etc.
template <typename State>
class StateTransition {
Matrix<float> _m;
StateTransition():_m(State::size(), State::size()) {}
};
However, other answers here (and elsewhere) indicate that virtual static functions are not allowed (and some of them unhelpfully suggest that it "doesn't make sense" or "wouldn't be useful").
What is an idiomatic way to solve this problem, that makes it easy as possible for derived classes to follow the rules?
Although I'm not sure why you insist on using virtual functions and not numeric arguments passed to the constructor of the base class, there is a solution that involves virtual functions, but of a different class:
class StateVectorInfo {
public:
virtual int size() const = 0;
protected:
~StateVectorInfo () = default;
};
class PositionStateInfo : public StateVectorInfo {
PositionStateInfo (); // don't create other instances
public:
virtual int size() const;
static PositionStateInfo info; // single instance
};
PositionStateInfo PositionStateInfo::info; // a definition is needed
class StateVector {
float* _v;
public:
StateVector (const StateVectorInfo& info):
_v(new float[info.size()]) {
}
};

how can I create with Polymorphy 2D-Array of abstract class?

I want to have a 2D array of pointers that contains abstract classes called Piece. So I made a pointer to a 2D array of Piece in a class called Board that have private field of board -Piece** _board.
I tried to use vector or wrap the board field with class but apperently something went wrong..
class Piece
{
public:
Piece(bool, string);
Piece(){};
bool isChass(bool, Board*);
virtual int move(int x_src, int y_src, int x_dst, int y_dst, Board* board)=0;
virtual ~Piece();
bool get_isWhite();
string get_type();
Piece(Piece & other);
Piece& operator= (const Piece & other);
bool inRange(int, int);
protected:
bool _isWhite;
string _type;
};
class Board
{
public:
Board();
Board(const Board& other);
~Board();
Board& operator=(const Board &other);
Piece& getPiece(int i, int j){ return _board[i][j]; }
void game();
void deletePiece(int x, int y) { delete &_board[x][y]; }
void allocateBlankPiece(int x, int y) { _board[x][y] = *new Blank(); }
private:
Piece** _board;
bool _isWhiteTurn;
friend class Piece;
friend class Rock;
friend class Bishop;
friend class Queen;
friend class Knight;
friend class King;
friend class Pawn;
};
You can't use polymorphism for arrays.
An array contains contiguous elements of the same size. But polymorphic elements could be of different size, so that the compiler would not be able to generate code to properly indexing the elements.
You can eventually consider an array of pointers to polymorphic elements:
Piece*** _board; // store pointers to polyorphic elements
But it would be more practical and safer to use vectors:
vector<vector<Piece*>> _board; // Vector of vector of poitners to polymorphic elements
You could also consider even safer smart pointers:
vector<vector<shared_ptr<Piece>>> _board; // assuming that several boards or cells could share the same Piece.

C++: Semantics for read-only and write-only versions of a class

In my program, I have a data structure called Foo. One part of the program constructs Foo from a set of parameters and so need access to mutative methods. Another part of the program will only read from Foo and so should not have access to mutative methods.
What is the best way to accomplish this, or am I taking the wrong view of how classes should work? I've used this way in the past:
class FooR {
public:
int read() { return x; }
protected:
int x;
};
class FooRW : public FooR {
void mutate(int nx) { x = nx; }
};
But this way feels like you're abusing inheritance and I think it might cause confusion to have two very similarly named classes in two parts of the program. Are there better ways? Can you use const in some tricky way?
EDIT:
#jens pointed out that using const references in the read-only part of the program should work, which made me realize it's important to know that my data structure is actually a tree, something like:
class Foo {
public:
void splitNode();
Foo *getChild(int n) const; // const Foo?
private:
Foo *children[2];
};
Is there a way of forcing a const Foo to return only const references to its children?
The parts of your program which do not need to change the object should just usr const references, and mark the non-mutating member functions as const.
class FooR {
public:
int read() const { return x; }
void mutate(int nx) { x = nx; }
private:
int x;
};
void f1(FooR const& obj)
{
int x = obj.read();
// cannot use obj.mutate(x+1);
}
void mutatingFunction(FooR&);
You could do the construction in a factory or build, and return a std::unique_ptr<FooR const> or a std::shared_ptr<FooR const> to prevent anybody else from using the mutating interface.
The same approach works for the tree. Declare a const-overload returning Foo const*, and a non-const overload returning a non-const pointer. The later one cannot be used from const references.
class Foo {
public:
void splitNode();
Foo const* getChild(int n) const;
Foo* getChild(int n);
private:
Foo *children[2];
};