I have a problem when i want to create a pure virtual function and assign to this multiple range of output formats (like int, double and char).
i wrote below code and it works only when i eliminate my abstract class which it's not thing that i want.
my code:
enter code here
//class DynamicArray
//{
// public:
// virtual void GetData(unsigned int s, int& d) = 0;
// virtual void SetData(unsigned int s, int& d) = 0;
//};
class DynamicArrayDouble//: public DynamicArray
{
private:
unsigned int m_Length;
double* arr;
public:
DynamicArrayDouble(unsigned int l)
{
m_Length = l;
arr = new double[m_Length];
}
void SetParam(unsigned int l)
{
m_Length = l;
arr = new double[m_Length];
}
void GetData(unsigned int s, double& d)
{
d = arr[s];
}
void SetData(unsigned int s, double& d)
{
arr[s] = d;
}
};
when i uncomment DynamicArray class and DynamicArrayDouble inherit it i face with some error. it should be noted, first time i try to use void* for second parameter for Set and Get methods, but again i receive some errors that i can't use this code style like this:
error: cannot declare variable 'd1' to be of abstract type 'DynamicArrayDouble'
and code of above error is:
class DynamicArray
{
public:
virtual void GetData(unsigned int s, void* d) = 0;
virtual void SetData(unsigned int s, void* d) = 0;
};
class DynamicArrayDouble: public DynamicArray
{
private:
unsigned int m_Length;
double* arr;
public:
DynamicArrayDouble(unsigned int l)
{
m_Length = l;
arr = new double[m_Length];
}
void SetParam(unsigned int l)
{
m_Length = l;
arr = new double[m_Length];
}
void GetData(unsigned int s, double* d)
{
*d = arr[s];
}
void SetData(unsigned int s, double* d)
{
arr[s] = *d;
}
};
int main()
{
DynamicArrayDouble d1(5);
double x=0;
for(unsigned int i=0;i<5;i++)
{
x = ((i+1.0)/2);
d1.SetData(i,&x);
}
for(unsigned int i=0;i<5;i++)
{
d1.GetData(i,&x);
cout << "Data " << i+1 << " is = " << x << endl;
}
return 0;
}
i write my codes in codeblocks.
i will appreciate your answer... Thank you.
You can't simply override
void func(some_pointer_type ptr);
with
void func(some_other_pointer_type ptr);
and same goes for references. Those are in fact considered to be completely unrelated if they don't match.
DynamicArrayDouble - this name tells me you should look into templates and not write the same code for all the types you'll need. This is how STL works. You'll completely avoid runtime polymorphism.
For starters:
template <typename T>
DynamicArray;
Related
If I have a friend function can I somehow use set() to assign a value to a private variable inside the function? Or some other method?
Example : Here I have 3 private variables. I tried to make the sum of 2 of them and store the result in the 3rd one. I tried to do it with a setter but the result is 0. In main it works, but I don't know if I can make it work in the class function.
#include <iostream>
using namespace std;
class Function{
private:
int a;
int b;
int sum;
public:
Function() = default;
Function(int _a, int _b);
friend int sumNumber(Function f);
//Setter and getter
int getA() const;
void setA(int a);
int getB() const;
void setB(int b);
int getSum() const;
void setSum(int sum);
};
Function::Function(int _a, int _b) {
this->a = _a;
this->b = _b;
}
int Function::getA() const {
return a;
}
void Function::setA(int a) {
Function::a = a;
}
int Function::getB() const {
return b;
}
void Function::setB(int b) {
Function::b = b;
}
int Function::getSum() const {
return sum;
}
void Function::setSum(int sum) {
Function::sum = sum;
}
int sumNumber(Function f) {
int a = f.getA();
int b = f.getB();
int sum = a + b;
f.setSum(sum);
return sum;
};
int main() {
Function AA(1,2);
cout << sumNumber(AA);
cout << " " << AA.getSum();
AA.setSum(sumNumber(AA));
cout << "\n" << AA.getSum();
return 0;
}
Output :
3 0
3
As alluded to in the comments, the issue is with this function:
int sumNumber(Function f) {
int a = f.getA();
int b = f.getB();
int sum = a + b;
f.setSum(sum);
return sum;
};
Let us walk through your code:
Function AA(1,2);
You create a object of type Function, called AA and you allocate each member variable of that object via the constructor (1 and 2).
cout << sumNumber(AA);
You call your method (sumNumber) and pass to it a copy of your variable AA. That function adds the two numbers together and internally calls setSum.
cout << " " << AA.getSum();
You now try to display the sum value by calling the getSum method. But the issue was that you passed a copy of your variable into the sumNumber function. The original AA variable was left alone.
To fix this you need to adjust your function by adding an ampersand &. Like this:
int sumNumber(Function& f) {
int a = f.getA();
int b = f.getB();
int sum = a + b;
f.setSum(sum);
return sum;
};
Now your variable AA is being passed by reference and not by value. There are lots of tutorials about this concept.
In the following code I made a template class, Its initialized in main function and I'm trying to assign char* as you can see below but It isn't working. I think the issue is in assign operator function I defined in Proxy class but I can't figure it out
#include <iostream>
using namespace std;
template <class T>
class Vector {
public:
T *p;
Vector(int size) {
p = new T[size];
}
class Proxy {
Vector &a;
int i;
public:
Proxy(Vector &a, int i) : a(a), i(i) {
}
void operator=(const T x) {
a.p[i] = x;
}
};
Proxy operator[](int i) {
return Proxy(*this, i);
}
};
int main() {
Vector<char *> sv1(2);
sv1[0] = "John";
sv1[1] = "Doe";
}
I'm getting following error;
I already tried setting parameter in assignment operator function to const, I also tried implicitly typecasting to T nothing has worked
Try this:
using namespace std;
template <class T>
class Vector {
public:
T* p;
int sz;
Vector(int size) {
p = new T[size];
sz = size;
}
template<class T>
class Proxy {
Vector<T>& v;
int i;
public:
Proxy(Vector<T>& vec, int index) :v(vec),i(index) { }
void operator= (const T val) { v.p[i] = val; }
};
Proxy<T> operator[](int index) { return Proxy<T>(*this, index); }
};
Your code will work with any basic type, (int, char, double) and pointers, but not, for example, with this:
int main() {
Vector<char*> sv1(2);
sv1[0] = "John";
sv1[1] = "Doe";
}
Firstly, the Vector points to a char*, not a string literal (const char*). You'd have to cast it using a C-style cast or a const_cast. Example:
int main() {
Vector<char*> sv1(2);
sv1[0] = const_cast<char*>("John"); //succeeds
sv1[1] = (char*)"Doe"; //succeeds
sv1[0] = "John"; //fails
sv1[1] = "Doe"; //fails
}
A string literal is always a const char* in C++.
You'll have same error writing code:
char * whatever = "something";
This code is absolutely wrong at least for string:
void operator=(const T x)
{
a.p[i] = x;
}
Step 1: allocate buffer;
Step 2: copy string to allocated buffer.
Your code is OK for primitives like char, int, etc. The following code should work:
int main() {
Vector<char> sv1(2);
sv1[0] = 'J';
sv1[1] = 'D';
}
I have an abstract parent class, let's call it A, and three child classes that inherit from it: a_B, a_C, and a_D. I have a sorting method that should be able to sort an array of any of these classes (a_B, a_C, or a_D) based on a rating property that they inherit from their parent, A.
I am having trouble implementing this, however.
Here's essentially what I have:
class A {
protected:
int rating;
A(int r) {
this->rating = r;
}
public:
int getRating() {
return rating;
}
virtual void abstractStuff() = 0;
}
class a_B : public A {
int property;
public:
a_B(int r, int p) : A(r) {
this->property = p;
}
void abstractStuff() {
cout << "a_B" << endl;
}
}
class a_C : public A {
float property;
public:
a_B(int r, float p) : A(r) {
this->property = p;
}
void abstractStuff() {
cout << "a_C" << endl;
}
}
class a_D : public A {
string property;
public:
a_B(int r, string p) : A(r) {
this->property = p;
}
void abstractStuff() {
cout << "a_D" << endl;
}
}
void sort(A* arr[]) {
//sort implementation
}
int main() {
a_B arr[5];
//code to give each element of arr unique properties
sort (arr); //doesn't work; this is where I'm kind of unclear about what to do
}
The last part, where I sort arr, is unclear to me. I'm not sure if I should pass a_B*, as a pointer, or maybe to cast it to type A, like (A) a_B or (A*) a_B or something of the sort.
edit:
The compiler gives me an error of an invalid conversion from a_B to A**.
Definitely your sort function takes an array of pointers to base class A, as the only argument. Probably, the idea is to achieve type erasure (to place in array elements of different dynamic types) and further you will be able to treat elements polymorphically. So, your arr argument will contain elements of type A*, and when you extract some element from array, you can extract its rating member for sorting purpose. Very important, you need to change to
a_B arr[5]; to A* arr[5];
also, every class constructor has the same name as class, so if we suppose that you made mistype, for example class a_D should looked like
class a_D : public A {
string property;
public:
a_D(int r, string p) : A(r) {
this->property = p;
}
void abstractStuff() {
cout << "a_D" << endl;
}
}
To mention also, that A as a base class, in implementation like yours, should have virtual destructor, or you will have leaks!!!
Further, to populate an array to be passed to sort, you need some kind of space allocated for array, on stack or heap (you choose stack), what ever, but be careful about lifetime issues, anyway. Once, when you have space for elements of an array of A* every element can be populated with A* which can be initialized with a_B* or a_C* or pointer to object of any derived class from A. Such an array, you can pass to sort function as argument, without any casting.
example code, you should be able to compile and run out of the box:
#include <iostream>
using namespace std;
class A {
protected:
int rating;
A(int r) {
this->rating = r;
}
public:
int getRating() {
return rating;
}
virtual ~A(){}
virtual void abstractStuff() = 0;
};
class a_B : public A {
int property;
public:
a_B(int r, int p) : A(r) {
this->property = p;
}
void abstractStuff() {
cout << "a_B" << endl;
}
};
class a_C : public A {
float property;
public:
a_C(int r, float p) : A(r) {
this->property = p;
}
void abstractStuff() {
cout << "a_C" << endl;
}
};
class a_D : public A {
string property;
public:
a_D(int r, string p) : A(r) {
this->property = p;
}
void abstractStuff() {
cout << "a_D" << endl;
}
};
template<class T, size_t N>
void printRatings(T*(&arr)[N]) {
for (size_t i=0; i<N; ++i) {
cout<< "rating["<< i <<"] = " << arr[i]->getRating() << "\n";
}
}
int main() {
A* arr[5];
a_B b(1,1);
a_C c(2,2.);
a_D d(3,"3");
arr[0] = &b;
arr[1] = &c;
arr[2] = &d;
arr[3] = &c;
arr[4] = &b;
printRatings (arr); //this works
return 0;
}
Note, that I used template function printRatings which takes
array of pointers to type T and deduces array size, so it can safely iterate through it.
the same idea you can use to make your sort function which will be like:
template<class T, size_t N>
void sort(T*(&arr)[N]) {
// sorting impl
}
and you will be able to pass A* arr[5] argument to it.
I am using a base class and a child class defined above main in main.cpp
this gives me an error of undefined reference FactoryTraversal::AddPoint::AddPoint(int const&, int const&, int)'
Here is the code:
#include <iostream>
#include <list>
#include <typeinfo>
#include <cmath>
enum traversal_type
{
TRAVERSAL = 0,
TRAVERSALMAX
};
template <class T>
class FactoryTraversal
{
public:
FactoryTraversal();
FactoryTraversal *CreateInstance(const traversal_type &type);
virtual ~FactoryTraversal();
const std::list<int>& GetIndices() const {return indices;}
int GetIndicesSize() const {return indices.size();}
virtual void AddPoint(const T &x, const T &y, int index);
protected:
std::list<int> indices;
};
template<class T>
class Traversal : public FactoryTraversal<T>
{
public:
Traversal();
void AddPoint(const T &x, const T &y, int index);
int GetResultXOR() const {return result_xor;}
private:
T coords_s[2];
T coords_e[2];
int result_xor;
void update_result(int index);
T calculate_distance(const T &x1, const T &x2, const T &y1, const T &y2);
};
template<class T>
Traversal<T>::Traversal():FactoryTraversal<T>()
{
//Do nothing
}
template<class T>
void Traversal<T>::AddPoint(const T &x, const T &y, int index)
{
if (0 == this->GetIndicesSize())
{
this->indices.push_front(index);
coords_s[0] = x; coords_s[1] = y;
coords_e[0] = x; coords_e[1] = y;
}
else
{
T d1 = this->calculate_distance(x,coords_s[0],y,coords_s[1]);
T d2 = this->calculate_distance(x,coords_e[0],y,coords_e[1]);
if (d1 < d2)
{
this->indices.push_front(index);
coords_s[0] = x; coords_s[1] = y;
}
else
{
this->indices.push_back(index);
coords_e[0] = x; coords_e[1] = y;
}
}
this->update_result(index);
}
template<class T>
T Traversal<T>::calculate_distance(const T &x1, const T &x2, const T &y1, const T &y2)
{
if (typeid(T) == typeid(int))
{
return std::min(std::abs(x1-x2),std::abs(y1-y2));
}
return 0;
}
template<class T>
void Traversal<T>::update_result(int index)
{
if (0 == this->GetIndicesSize())
result_xor = index;
else
result_xor ^= index;
}
template<class T>
FactoryTraversal<T>::FactoryTraversal()
{
indices.clear();
}
template<class T>
FactoryTraversal<T>::~FactoryTraversal()
{
//Do Nothing
}
template<class T>
FactoryTraversal<T>* FactoryTraversal<T>::CreateInstance(const traversal_type &type)
{
if (TRAVERSAL == type)
return new Traversal<T>();
else
return NULL;
}
FactoryTraversal<int> factory_traversal;
Traversal<int> *traversal = new Traversal<int>();
int main()
{
int T;
std::cin>>T;
int output[T];
for (int i = 0; i < T; ++i)
{
int N;
std::cin>>N;
FactoryTraversal<int> factory_traversal;
FactoryTraversal<int> *traversal = factory_traversal.CreateInstance(TRAVERSAL);
for (int j = 0; j < N; ++j)
{
int x, y;
std::cin>>x>>y;
traversal->AddPoint(x,y,j+1);
}
Traversal<int> *tmp = dynamic_cast<Traversal<int> *>(traversal);
if (tmp)
output[i] = tmp->GetResultXOR();
else
output[i] = 0;
}
for (int i = 0; i < T; ++i)
{
std::cout<<output[i]<<std::endl;
}
return 0;
}
Interfaces in C++ are called "abstract classes", and classes are abstract if they have at least one "pure virtual function". A function is a pure virtual function if it is prefixed with virtual and has a trailing =0 in its declaration. This is what you want for FactoryTraversal::AddPoint:
virtual void AddPoint(const T &x, const T &y, int index) = 0;
Now the derived class is expected to define it (and it does). Without AddPoint being pure virtual, you are forced to provide an implementation for it in the base class, which you could do simply as:
virtual void AddPoint(const T &x, const T &y, int index){}
This gives a "default" or fallback implementation for when a derived class chooses not to override the method. If it were pure virtual, the derived class is forced to define it, lest a call to it result in a compiler error (otherwise the derived class is also considered abstract).
Note that destructors should never be pure virtual. The way you have it right now is great; you unconsciously followed the rules I've outlined above.
Some other notes:
Variable length arrays are not legal C++, this is a compiler extension:
int output[T]; // T is read from command line
Use a vector instead:
std::vector<int> output(T);
You have memory leaks as-is. Use a managed pointer like unique_ptr so you don't have to worry about new and delete
I stated that you wanted AddPoint to be pure virtual and I mean it. You code won't compile if that's the first step you take, though. It looks like you merged a base class and a factory into one; split those out.
Putting it all together we can define our new base class as:
template<class T>
class TraversalBase
{
public:
virtual ~TraversalBase(){}
const std::list<int>& GetIndices() const {return indices;}
int GetIndicesSize() const {return indices.size();}
virtual void AddPoint(const T &x, const T &y, int index) = 0;
protected:
std::list<int> indices;
};
The derived class becomes (very little change, also notice the override keyword):
template<class T>
class Traversal : public TraversalBase<T>
{
public:
void AddPoint(const T &x, const T &y, int index) override;
int GetResultXOR() const {return result_xor;}
private:
T coords_s[2];
T coords_e[2];
int result_xor;
void update_result(int index);
T calculate_distance(const T &x1, const T &x2, const T &y1, const T &y2);
};
And our Factory class is much simplified:
template <class T>
struct FactoryTraversal
{
FactoryTraversal(){}
std::unique_ptr<TraversalBase<T>> CreateInstance(const traversal_type &type);
~FactoryTraversal(){}
};
Live Demo (C++11)
I am a newbie in C++, while writing code to implement a smart pointer I came across this problem and having some confusion.
template<typename T> class SP
{
T* pData;
public:
SP(T* pValue) : pData(pValue)
{
// pValue = pData;
}
T& operator*()
{
return *pData;
}
T* operator->()
{
return pData;
}
};
class Shape
{
float length;
float breadth;
float area;
public:
Shape()
{ }
Shape(float i,float j)
{
length = i;
breadth = j;
cout<<"Constructor called\n";
cout<<length<<breadth<<endl;
}
void calculateArea()
{
area = length * breadth;
}
void display()
{
cout<<"Lenght = "<<length<<endl;
cout<<"Breadth = "<<breadth<<endl;
cout<<"Area = "<<area<<endl;
}
};
int main()
{
SP<Shape> ptr(new Shape(1.1,2.2));
ptr->calculateArea();
ptr->display();
return 0;
}
If I directly assign pValue = pData; I am seeing a memory fault where as when using the initializer the program is working fine.
SP(T* pValue) : pData(pValue)
Please help me understand how is the programming running fine when initializer list is used.
You've swapped the assignment around.
Instead of
pValue = pData;
You want to do
pData = pValue;