This is the rough outline of my code. I've left out some details so let me know if you need more context.
class A;
class B;
class C {
public:
C(int dat, int idx) {
data = dat;
i = idx;
}
friend class A;
friend class B;
private:
int data;
int i;
};
class A {
public:
void insert(int dat, int idx) {
c = new C(dat, idx);
// ... other operations to place it
}
// I have the correct destructor, etc..
// function that returns an address to a specific instance of a dynamically allocated C
C* getPointer(int dat) const {
return getPointer(dat); // a call to an internal function
// omitted for simplicity because this works
}
private:
C* c;
};
class B {
public:
B() {
size = 5;
arr = new D[size];
}
// I have the correct destructor, etc..
C* getPtr(int idx) {
return(arr[idx].X);
}
void setPtr(C*& oldPtr, C* newPtr) {
oldPtr = newPtr;
}
private:
struct D{
int d;
C* X;
D() {
d = 0;
X = nullptr;
}
};
D* arr;
int size;
};
int main() {
A a;
B b;
// index is a value returned from an insert function in class B
// dat is a value to find which address should be returned of the objects in class A
a.setPtr(b.getPtr(index), a.getPointer(dat));
return 0;
}
I wrote a function (getPointer(int dat) in class A) that returns the address of an instance of the dynamically allocated object of class C. So, how do I update X to point at this address instead of null?
I've tried many different ways and currently (what I thought was the most promising) was the setPtr() function in class B. It correctly changes the address X is pointing to once, but when I call any other functions its value is back to nullptr.
Any help or advice would be greatly appreciated. Thank you.
You correctly wrote getPtr(int idx) (if I understand your spec. correctly). Now, the return value is C* there, which is not C*& or C**, so it won't be updated if you change the result afterwards - think of it as a return i; won't expose int i; member if return type is int.
So either:
you need to change the return type of getPtr(int idx) and then setPtr() is not really needed;
or you can build both of these in setPtr() as:
void setPtr(int idx, C* newPtr) {
arr[idx].X = newPtr;
}
Related
I am trying to create a map containing shared_ptr as values.In the function deleteB, I iterate through the map looking for a particular key value, when found, I erase the particular key, value pair and break out of the for loop, but as soon I come out of the deleteB function, the program crashes.I used address sanitizer and it shows heap use after free error.Not sure, where exactly this crash is happening.
struct MyObj{
int val;
void* ctx;
};
class A{
private:
MyObj obj;
int countVal;
public:
A(int value){
countVal = value;
obj = (MyObj){countVal, this};
}
~A(){}
MyObj getObj(){
return obj;
}
};
class B{
private:
int count = 0;
map<uint32_t, shared_ptr<A>> mB;
public:
void createB(MyObj &obj, int &getCount){
++count;
mB[count] = make_shared<A>(count);
obj = mB[count]->getObj();
getCount = count;
}
void deleteB(int Val){
if(!mB.empty()){
for(auto &a : mB){
if(a.first == Val){
mB.erase(a.first);
break;
}
}
}
}
};
int main(){
B b;
MyObj objVal;
int count = 0;
b.createB(objVal, count);
b.deleteB(count);
return 0;
}
I have a class MyClass and another class that holds an array of MyClass, as follows:
class MyClass {
int a;
float b;
void SetInt(int value)
{
a = value;
}
void SetFloat(float value)
{
b = value;
}
}
class MyClassArray {
std::vector<MyClass> classList;
}
What is the easier way to create a new MyClass, insert an object in MyClassArray and call the methods to store value on it ?
Can I just create a temporary MyClass and insert it on the vector, calling the function in one statement ? Like:
classList.push_back(MyClass().SetInt(21));
classList.push_back(MyClass().SetFloat(1.23));
Is that valid ?
BTW: I need in vector a one object MyClass with 21 set on a and another one with 1.23 set on b, that´s why I´m not using initializers for a and b.
you can use chaining :
class MyClass {
int a;
float b;
public:
MyClass& Set(int value) { a = value; return *this; }
MyClass& Set(float value) { b = value; return *this; }
};
this enables thing like:
MyClass a;
a.Set(1).Set(1.5f);
and also:
vector<MyClass> vec;
vec.push_back(MyClass{}.Set(3));
Use your constructor
class MyClass {
int a;
float b;
}
class MyClassArray {
std::vector<MyClass> classList;
classList.push_back(MyClass(21,1.23));
}
You can use constructors for this. If you overload the constructor to take either an int or a float you would be able to set the value for both of the situations that you outlined.
class MyClass
{
int a;
float b;
MyClass(int i) : a(i) { }
MyClass(float f) : b(f) { }
}
this way you could add objects to the vector by doing this:
std::vector<MyClass> classList;
classList.push_back(MyClass(21));
and by doing this:
classList.push_back(MyClass(1.23));
If you really need to call a separate method you could do it like this:
class MyClass {
int a;
float b;
MyClass& SetInt(int value)
{
a = value;
return *this;
}
MyClass& SetFloat(float value)
{
b = value;
return *this;
}
}
Which will return a reference to the class. It is far better to do it using constructors though.
Given class A and Class B. I need to use the "add" function as shown in the cpp file to store an object reference of class B in an object array of class A.
I should be able to use "->" as shown in the cpp file to call Class B's "print" function.
Compile Time Error: void* is not a pointer-to-object type
So how do I solve this error?
==================================================================================
// header file
// ABC.h
class A{
private:
size_t size_;
void * a_[256];
static int index_;
public:
void add(void * obj);
void * operator[](int x){
return a_[x];
}
};
class B {
private:
const char * f_;
const char * l_;
public:
B(const char * fn, const char * loc ):f_(fn), l_(loc){ A(); };
void print();
};
// cpp file
#include "ABC.h"
int A::index_ = 0;
inline void A::add(void* obj){
void * insertionPoint = static_cast<char *>(a_[index_]) + ( size_ * index_ );
memcpy( insertionPoint, obj, size_);
++index_;
}
inline void B::print(){
...
}
int main()
{
A a;
B b( "Name", "Some string");
a.add( &b );
a[0]->print(); // <-- This should be an object reference to B, but it is producing the error.
return 0;
}
Output:
Name Some string
The following method makes no sense:
virtual void add(A * obj){
*this = dynamic_cast<void*>(obj);
}
in case you want to store pointers to other instances of A within A, create an array of pointers where you will hold them, trying to "replace" the current instance (i.e. *this =...) makes no sense.
Also note that dynamic_cast would make sense if you want to examine whether A* points to instance of B:
A* a = new B();
// in compile time it's A*, but does it really point to instance of B? :
B* b = dynamic_cast<B*>(a);
Why don't you start with something simpler? Let's say:
class A {
public:
virtual void print() { std::cout << "a"; }
};
class B : public A {
public:
void print() /* const */ { std::cout << "b"; }
};
used as:
A* a = new A();
A* b = new B();
a->print();
b->print();
which (as it stands) outputs ab. Then you can change the B's print() to const and realize that the constness of method actually matters.
The solution involved advice from all above comments
Compare the differences between the question and answer to see the solution, fully.
What I needed to do was change class A's private a_ member to type A: A * _a[256]
NEXT: I needed to change the operator[] and the add method's parameter to type A, as well: A * operator[](A * obj)
NEXT: I needed to add a virtual void print()for inheritance purposes to class A.
FINALLY: Class B needed to inherit class A
Below is working code
NOTE: I am not sure if this code is entirely secure or deals with memory issues properly, but I do know that it prints to output what it was intended to print.
==================================================================================
// header file
// ABC.h
class A{
private:
size_t size_;
A * a_[256];
static int index_;
public:
void add(A * obj);
A * operator[](int x); // Any subclass object reference of A can be assigned now.
virtual void print()const; // Virtual tells the compiler to look for other void print methods first.
};
class B : public A{
private:
const char * f_;
const char * l_;
public:
B(const char * fn, const char * loc ):f_(fn), l_(loc){ A(); };
void print()const;
};
// cpp file
#include "ABC.h"
int A::index_ = 0; // Need to call this here because it is declared static in Class A and can be used dynamically.
inline A * A::operator[](int x){
return a_[x]; // Implements operator[], so class A can act like a container.
}
inline void A::add(A* obj){
a_[index_] = obj; // Adds a base or subclass object reference to class A object array.
++index_; // Need this to remember current index of object reference A's array.
}
inline void A::print()const{}
inline void B::print()const{
std::cout << "B " << firstname_ << " works in " << location_ << std::endl;
}
int main()
{
A a;
B b( "Name", "Some string");
a.add( &b );
a[0]->print();
return 0;
}
Output:
Name Some string
I am making my first steps in learning OOP . And here is the first problem which I can't solve.
The max function in this class should return the maximum of two numbers . I want to keep the numbers in the private scope and the functions in the public scope . But when I want to use variables from struct data{} in the public scope the compiler says that the variables are not declared . Please tell me why I get these errors .
class myclass{
private:
struct data{
int q ;
int w;
};
public:
void get(int a, int b){
struct data = {a , b}; // here I want to pass the variables to data struct
}
int max (){ // this function returns the biggest number
if(q>w)
return q;
else
return w;
}
};
struct data{
int q ;
int w;
};
only declares a type, not an object, so there are no q and w members anywhere inside your class instances. You need the declare an instance of the struct:
struct {
int q;
int w;
} data;
Then, you can write max as:
int max()
{
if (data.q > data.w)
return data.q;
else
return data.w;
}
(I've no idea what your get method is supposed to do, so I have no replacement for that.)
In C++ "class" and "struct" are close to being synonymous (the same thing). The ONLY difference is that a "struct" defaults to being "public" accessibility while a "class" defaults to private.
Once you understand this, it should become obvious that what you are doing is defining a sub-type within your class.
class myclass {
private: // <- not required, you already said that by saying "class".
struct data {
// <-- this is a class definition with "public:" just here.
...
};
};
C++ allows you to nest class/structure definitions so that you can, for example, create structures that marshal parameters or return values.
class Database {
class Result { ... };
};
...
class Exam {
class Result { ... };
};
These two result classes avoid namespace collision, by being Database::Result and Exam::Result instead of just "Result".
However - these are only definitions. They do not - as shown - have any effect on the outlying class, that is: they aren't being used to add a member to the class.
Your code:
class myclass{
private:
struct data{ // <-- this is a TYPE declaration, struct myclass::data
int q ; //
int w; //
}; // <-- no member name here so does not affect myclass itself.
public:
void get(int a, int b){
struct data = {a , b}; // here I want to pass the variables to data struct
}
int max (){ // this function returns the biggest number
if(q>w)
return q;
else
return w;
}
};
Declares a type "myclass::data" but does not add a member of type "myclass::data" to the class. The line "struct data = " is illegal, you're trying to assign values to a TYPE.
It should probably be written as
class MyClass {
int m_q;
int m_w;
public:
void set(int q, int w) {
m_q = q;
m_w = w;
}
int max() const {
return (m_q > m_w) ? m_q : m_w;
// or #include <algorithm> and return std::max(m_q, m_w);
}
};
You only need to hoist q & w into a struct if you are going to reuse that structural definition outside the confines of the class, e.g. in derived or parallel classes where you may want to add more of the same type of thing, in which case, you could perhaps do the following, but if you do it this exact way you'll eventually kick yourself for breaking encapsulation:
class MyClass {
public:
struct Data {
int m_q;
int m_w;
};
private:
Data m_data;
void set(int q, int w) {
m_data.m_q = q;
m_data.m_w = w;
}
int max() const {
return (m_data.m_q > m_data.m_w) ? m_data.m_q : m_data.m_w;
}
};
A better way, if this coupling of members needs to be externally visible to some degree would be:
class MyClass {
public:
class Data {
int m_q;
int m_w;
public:
Data() : m_q(0), m_w(0) {}
Data(int q, int w) : m_q(0), m_w(0) {}
void set(int q, int w) {
m_q = w;
m_w = w;
}
int q() const { return m_q; }
int w() const { return m_w; }
int max() const { return (m_q > m_w) ? m_q : m_w;
};
private:
Data m_data;
public:
MyClass() : m_data() {} // or = default
MyClass(int q, int w) : m_data(q, w) {}
MyClass(const Data& data) : m_data(data) {}
// Read-only access
const Data& data() const { return m_data; }
// To allow write access, e.g. for set:
Data& data() { return m_data; }
};
It's kinda overkill for such a simple case, but welcome to C++: the boilerplate language.
You have defined the structure but there is no object of that type. You should declare an object and you will not get any error.
class myclass{
private:
struct data{
int q ;
int w;
}var;
public:
void get(int a, int b){
var .q= a;
var.w=b; // here I want to pass the variables to data struct
}
int max (){ // this function returns the biggest number
if(var.q>var.w)
return var.q;
else
return var.w;
}
};
class c {
private:
int n[10];
public:
c();
~c();
int operator()(int i) { return n[i];};
};
class cc {
private:
public:
c *mass;
cc();
~cc();
c& operator*() const {return *mass;};
};
int somfunc() {
c *c1 = new c();
cc * cc1 = new cc();
(*cc1->mass)(1);
delete c1;
}
I've got a pointer into class cc to class c.
Is there any way to get rid of record like this:
(*cc1->mass)(1);
and write somethink like that:
cc1->mass(1);
is it impossible?
When I saw the tags "c++" and "operator overloading", my mind alarm turns ON.
C++ operator overloading is complex, and some operators like "()" or "->" make it more difficult.
I suggest, before overloading operators, making either a global function or method with the same purpouse, test it works, and later replace it with the operator.
Global friend function example:
class c {
private:
int n[10];
public:
c();
~c();
// int operator()(int i) { return n[i]; }
// there is a friend global function, that when receives a "c" object,
// as a parameter, or declares a "c" object, as a local variable,
// this function, will have access to the "public" members of "c" objects,
// the "thisref" will be removed, when turned into a method
friend int c_subscript(c thisref, int i) ;
};
int c_subscript(c* thisref, int i)
{
return c->n[i];
}
int main()
{
c* objC() = new c();
// do something with "objcC"
int x = c_subscript(objC, 3);
// do something with "x"
return 0;
} // int main(...)
Local function ( "method" ) example:
class c {
private:
int n[10];
public:
c();
~c();
// int operator()(int i) { return n[i]; }
int subscript(int i) ;
};
int c::subscript(int i)
{
return this.n[i];
}
int main()
{
c* objC() = new c();
// do something with "objcC"
int x = c->subscript(objC, 3);
// do something with "x"
return 0;
} // int main(...)
And, finally use the overloaded operator:
class c {
private:
int n[10];
public:
c();
~c();
int subscript(int i) ;
int operator()(int i) { return this.subscript(i); }
};
int c::subscript(int i)
{
return this.n[i];
}
int main()
{
c* objC() = new c();
// do something with "objcC"
int x = c->subscript(3);
// do something with "x"
int x = c(3);
// do something with "x"
return 0;
} // int main(...)
Note that in the final example, I keep the method with a unique identifier.
Cheers.
Could always do this:
class cc {
private:
c *_mass;
public:
c& mass() const {return *_mass;};
};
Now..
cc1->mass()(1);
If mass were an object, not a pointer, you could use the syntax you want:
class cc {
private:
public:
c mass;
cc();
~cc();
const c& operator*() const {return mass;};
};
…
cc1->mass(1);
You can with
(*(*cc1))(1)
because operator() is applied to an object, not a pointer.
You can use
(**cc1)(1);
Or
cc1->mass->operator()(1);