Initialise values of a struct for use in another file - c++

So I have my class Test.H which has a struct in it.
Class Test{
private:
struct Data
{
char *first;
int number;
int count;
};
Data *myStruct;
I am trying to use the myStruct in my User.C initialiser.
//User.C
#include "Test.H"
Test::Test(const char *alp){
myStruct.number = 0;
}
And I get an segmentation fault and error from valgrind.
I figured initially that it was due to Data* myStruct being in private, but after writing a function like this below:
Data getStruct(){
return myStruct;
}
It will still give me errors when I use it in User.C

You need to construct the struct before you can do anything with it. Calling the default constructor will initialises it's fields to 0.
You had class capitalised, that was wrong. I also don't see a reason why it has to be a pointer, so I removed that. Lastly, I added a destructor in Data so that first will be deleted. I assume it is a cstring, so I used delete[]. If it is something else, delete it in whatever manner is appropriate.
If you must have a pointer, modify the call to the constructor to use new, delete the struct in the destructor ~Test(), and reference members of myStruct with the -> operator.
class Test {
public:
struct Data {
const char* first;
int number;
int count;
~Data() {
delete[] first;
}
};
Test(const char *alp) {
// Default constructor initialises struct's fields to 0.
myStruct = Data();
myStruct.count = 7;
}
private:
Data myStruct;
};

Related

c++ setter/getter does not work as expected

for some reason my prof insists I have to use setter/getter everywhere.
Well... in this linked list I don't understand why this one doesn't work
#include <iostream>
#include <string>
using namespace std;
class SomeClass{
string some_string;
public:
void setSomeString(string s);
string getSomeString();
};
void SomeClass::setSomeString(string s){
some_string = s;
}
string SomeClass::getSomeString(){
return some_string;
}
class Node{
SomeClass some_class;
Node *next;
public:
void setSomeClass(SomeClass sc);
SomeClass getSomeClass();
//...
};
void Node::setSomeClass(SomeClass sc){
some_class = sc;
}
SomeClass Node::getSomeClass(){
return some_class;
}
class List{
public:
Node *head, *ptr;
//...
};
int main(){
List l;
l.head = new Node();
l.head->getSomeClass().setSomeString("a string");
cout << l.head->getSomeClass().getSomeString();
return 0;
}
I expect in the output "a string", instead is empty... What am I doing wrong?
Node::getSomeClass() method returns something by value. This means that the returned object is a copy which means that now you have two different objects and there is no side effect.
If you want to edit the original value you need to return it by reference:
SomeClass& getSomeClass() {...}
In this way you will get the reference of the original object and you can edit it.
Don't wrap something if wrapper adds nothing to wrapped like SomeClass adds nothing to string except useless set/get.
Even if Node::getSomeClass() returns by reference why it's private in Node? If private member returned by reference it can be abused outside of Node.
If you insist to make SomeClass private in Node then l.head->getSomeClass().setSomeString("a string") should be l.head->setSomeString("a string") where:
void Node::setSomeString(string input){
some_class.setSomeString(input); //while not exposing some_class at all
}

Destructor for pointer and non pointer

Why this can't work. Is there any way to do this?
I don't want to create a separate function for pointers
#include <iostream>
using namespace std;
template<class T>
class temp
{
public:
T val;
temp(T value) : val(value) {}
~temp()
{
if(is_pointer<T>::value)
{
delete val;
}
}
};
int main()
{
string * n = new string("cat");
temp<string*>object(n);//ok
temp<string>object2("dog"); //compliation error: type 'class std::cxx11::basic_string' argument given to 'delete', expected pointer. --- (but there is if statement!!!!)
//i dont want delete in main
return 0;
}
To compile i use g++ 6.3.0
Could someone help? Maybe, I need to separate declaration from definition?
The issue that you have is that the branch of an if must always be syntactically valid, even if it is never taken.
You could do it with if constexpr, which is a "compile time if"
~temp()
{
if constexpr(is_pointer<T>::value)
{
delete val;
}
}
However this isn't safe.
How do you know that the pointer passed to temp<T*> was created by new and not new[], malloc, or by taking the address of an object that wasn't dynamically allocated?
Rather than assume that pointers should be deleted, you should avoid having to know which pointers to delete
#include <string>
#include <memory>
template<class T>
class temp
{
public:
T val;
temp(T value) : val(value) {}
// n.b. no need to define destructor
};
int main()
{
std::string str("cat");
temp<std::string*> object(&str);//ok
temp<std::string> object2("dog"); // also ok
std::unique_ptr<std::string> str2 = std::make_unique<std::string>("mouse");
temp<std::string *> object3(str2.get()); // ok so long as str2 outlives object3
std::shared_ptr<std::string> str3 = std::make_shared<std::string>("rabbit");
temp<std::shared_ptr<std::string>> object4(str3); // also ok
return 0;
}

Pointer in constructor and member function return different addresses

HelloI got a problem when i compiled my program.
Why the pointer intArray gives different addresses in constructor and member function display() in same object?Thank you!
#include<iostream>
using namespace std;
class MyClass
{ private:
int* intArray;
int arraySize;
public:
MyClass(int*,int);
~MyClass()
{delete []intArray;};
void display();
};
MyClass::MyClass(int intData[],int arrSize)
{ int *intArray = new int[arrSize];
cout<<intArray<<" "<<endl;
};
void MyClass::display()
{ cout<<intArray<<" "<<endl;
}
int main()
{ int Data[10]={9,8,7,6,5,4,3,2,1,0};
MyClass obj1(Data,10);
obj1.display();
}
In the constructor, you declare a local variable which hides the member. Both members are left uninitialised, so calling display will show the uninitialised value.
You probably want something along the lines of
MyClass::MyClass(int intData[],int arrSize) :
intArray(new int[arrSize]),
arraySize(arrSize)
{
// assuming the input array specifies initial values
std::copy(intData, intData+arrSize, intArray);
}
Since you're dealing with raw pointers to allocated memory, remember to follow the Rule of Three to give the class valid copy semantics. Then, once you're happy with your pointer-juggling skills, throw it away and use std::vector instead.

Right way to initialize a pointer in a constructor

I have the following exercise:
Add code to make it run properly.
class MyInt
{
public:
private:
int* MyValue;
}
int main(int argc,char** argv)
{
MyInt x(1);
...//a bit more code where the actual value of x is going to be used.
return 0;
}
I added as a private property
int val;
and a public constructor
Myint(int x)
{
val = x;
MyValue = &val;
}
I added the int val as a way for the constructor to assign to MyVal an address of an object that is not temporary, as the x.
Is there a neat(er) way to answer this exercise?
I don't see anything in your original problem statement that requires the pointer to be initialized to the address of an int. The minimal code required to fix the example would be to add a constructor that takes an int, and initialize MyValue to nullptr.
class MyInt
{
public:
MyInt(int) {}
private:
int* MyValue = nullptr;
};
int main(int argc,char** argv)
{
MyInt x(1);
return 0;
}
If your compiler doesn't support C++11 then
class MyInt
{
public:
MyInt(int) : MyValue(NULL) {}
private:
int* MyValue;
};
Another way:
MyInt(int x) : MyValue(new int(x)) {}
This doesn't require the additional member. However, you have to make sure that you deallocate the memory in the destructor.
~MyInt() { delete MyValue; }
I'm not really sure why you want to store a pointer to an int inside a class, rather than just storing the value directly (and not have a pointer be the input to the constructor), but assuming you do actually want that, here's how you'd do it:
MyInt(int x):MyValue(new int(x)){}
But this is really, really terrible style, and you have to have a good reason for doing it. You also need to remember to free the pointer at class destruction:
~MyInt(){delete MyValue;}

dynamic memory allocation

how allocate memory dynamically for the array of stucture....
eg:
class students
{
struct stud
{
int r_no;
char name[20];
}*s;
}
how to allocate memory dynamically for *s...
First of all, this is not the way of doing it, as you could use a vector of stud, for instance. With the code as you have it, it would be something like:
class students
{
public:
struct stud ... *s;
students() // ctor
{
s = new stud[100]; // say you have 100 students
// from now on you can use s[0], s[1], etc. in the class
}
};
However, what you should be using is kind of an STL vector or list:
class students
{
public:
struct stud ... ;
std::vector<stud> my_students;
students() // ctor
{
stud aStudent = {0, "Student Name"};
my_students.push_back(aStudent); // add a new student.
}
};
Why the extra wrapping of the struct in a class with nothing but a pointer?
Anyway, in C you'd do something like this:
struct stud
{
int r_no;
char name[20];
} *s;
size_t num_students = 4711;
s = malloc(num_students * sizeof *s);
Then it'd be prudent to go through and make sure all those individial structs are initialized, of course.
If you mean this to be C++, you should write constructors that take care of that, and use a new[] to allocate an array of structures.
You should make use of standard components when you can. Here std::string and std::vector would help you.
struct Student
{
int r_no;
std::string name;
};
typedef std::vector<Student> StudentList;
With such an approach, there is no point in wondering how to dynamically allocate memory. Everything's taken care of !
EDIT:
I simply typedef'ed StudentList because to me, adding more functionality to it would have been unrelated to the question.
Clearly, the last line can be replaced with a true class definition:
class StudentList
{
public:
// Add your own functionalities here
private:
std::vector<Student> m_students;
};
class students
{
public:
students(size_t noOfStudents):m_noOfStudents(noOfStudents)
{
s = new stud[m_noOfStudents];
}
~students()
{
delete s;
}
private:
struct stud
{
int r_no;
char name[20];
}*s;
size_t m_noOfStudents;
}