I have C# background and been working with C# for so many years.. Recently, I'm learning C++ and having some difficulties..
Basically, I'm trying to create the linked link class as below. I want to use my class as a data in struct node.
How can I fix this in C++? Thanks.
But it said that i can't use like that.
class Polynomial{
public:
Polynomial(pair<double, int>);
void add(Polynomial);
Polynomial multiply(Polynomial);
void print();
private:
struct node
{
Polynomial data;
node *link;
}*p;
};
Your node struct contains a member variable of type Polynominal, but since node itself is declared inside Polynominal, the declaration of Polynominal isn't complete at that point.
I get the impression that you assume classes in C++ to work just like C#, but they don't. C++ isn't garbage-collected, and it doesn't automatically manage references for you when you use classes. A class in C++ behaves more like a struct in C#, and when you pass or declare it like in your example, it gets copied by value.
Another thing: C++ comes with STL, which contains a range of templates for all sorts of things, including a nice linked list (std::list).
Couple of issues:
Polynomial doesn't have a default constructor, so the only way to create it is by using that custom constructor you have. However, your inner struct contains an object of type Polynomial. How is that supposed to be created? You can't embed objects that don't have a default constructor in classes unless you initialize them specifically in the container's constructor.
Your struct contains an object of the type of the parent class, which you're still in the process of defining! If anything, you need to make that struct its own class.
In general, you seem to do a lot by-value operations. This is very inefficient - you should always pass Polynomial by reference or pointer.
To fix it just use Polynomial &data; instead of Polynomial data; in the struct
Change that to Polynomial *data; and it will work just fine. And therein lies your clue as to what's wrong. Understanding that will bring great enlightenment.
One way of explaining it is that in C++ (unlike C#) a Polynomial and a float behave in exactly the same way with regards to how storage is allocated with them. In C# you can't do new float; (not to be confused with new Float();) and in C++ you can.
The points raised by EboMike are all valid, but just to make it compile (it's still unusable due to the constructability issue):
class Polynomial{
public:
Polynomial(pair<double, int>);
void add(Polynomial);
Polynomial multiply(Polynomial);
void print();
private:
struct node; // forward declaration creates incomplete type
node *p; // OK to have pointer to incomplete type
};
struct Polynomial::node
{
Polynomial data; // class Polynomial is complete now
node *link;
};
Related
So I am in process of coding class for some graph structure (suffix tree), and I encountered this difficult thing: a node should have pointers, one pointing on its parent, and also a set of pointers to its sons. I am using smart pointers to avoid errors with memory, and here is the thing: I write
class node {
...
std::shared_ptr<node> parent;
...
};
I guess there is a term for this thing. Like self-referencing, or whatever. When I wrote it, initialy i was confident, that there will be an error, but no it had been successfully compiled. I was curious, can i write something like that:
class some_class_2{
...
std::vector<some_class_2> some_vector;
std::string string_;
some_class() {
string_ = "lol";
some_vector = std::vector<some_class>(10);
}
};
Its appeared that the answer on this question is yes. So when i launched the test programm which had been succesfully compiled, of course it wouldn't stop, maybe i waited not enough and it should throw me some memory related error.
So the question is, how you should handle with this kind of things in c++? Isn't it strange that those things allowed in c++? Is it normal to put std::shatre_ptr inside some_class? How to write safe code, where errors like in some_class_2 are avoided, and what is the best way to
represent graph structure?
If the language did not allow any use of node inside the definition of node, then there would be no way to create linked data structures such as lists and trees. In order for the language to be useful, it has to allow such constructs as:
struct node {
int key;
node* next;
};
On the other hand, the language cannot allow this:
struct node {
int key;
node next;
};
because then a node object would contain an infinite nested sequence of node objects and be infinitely large.
The way the language deals with this is to allow members of classes only to be complete types. A complete type's size is known. A class type is not complete until its full definition has been seen. So node is not complete inside its own definition, so you cannot put a node member inside a node object. But node* is complete even when node is not complete yet.
Some standard library templates can be used with complete types. The smart pointers, std::unique_ptr<T>, std::shared_ptr<T>, and std::weak_ptr<T>, are allowed to have incomplete T, since they have pointer semantics. However, std::vector does not allow its template parameter to be incomplete, and the result is undefined behaviour. The way to avoid this is to just not write it (it's not that hard).
In c++, We all know that this code is wrong:
class Node {
public:
Node node;
};
However, declaring a vector like this is right, WHY?
class Node {
public:
std::vector<Node> nodeVec;
};
It works just fine in the C++14 compiler I'm using. And it provides a very convenient pattern for representing an arbitrarily large complex tree-shaped data structure inside a “single” instance. A nice property is that all storage management for the entire tree is handled automatically by std::vector. For example you can have a Node member variable in a class Foo and not worry about deleting the tree when you are done with the enclosing Foo instance.
As described elsewhere (How can I declare a member vector of the same class?) it is not a problem for the compiler because the size of std::vector<Node> itself is independent of the size of Node, because std::vector is a fixed size header with a pointer to a separate block of managed storage on the heap.
I have a class
class PCB {
public:
struct {
string type;
**linklist list;**//refer to list which contains PCB instance
} status;
}
what i want is to create the class PCB instance, but the instance is in a linklist list. i build the linklist class as below
class linklist
{
public:
void append( PCB num );
};
void linklist::append(PCB num){
}
Error occus saying num above is in error type. what shall i do in this case?
If you do not need the copy in your linklist::append method you could as well just use a (const) reference
void append(const PCB& num);
and forward declare PCB before in the same header file
class PCB;
You could do a forward declaration on one of the types but your really should ask yourself why you are doing this.
I cannot think of any time when this would be a good idea. If you think about your problem relative to the real world linklist is a collection of buckets. What you are asking for is a bucket (PCB) to hold a series (linklist) of buckets (PCB). In reality this would never work as a bucket cannot hold a collection of other buckets of the same size.
Another think to ask yourself, why would you use a link list when the STL (Standard Template Library) provides everything you would need and more already. I would highly recommend a vector if you list of PCB's are fairly static, or a list if not.
Linked lists can be very efficient for lightweight containers but you have to maintain them. If you using classes, GO WITH STL containers.
You can use forward declaration:
class linklist; // forward declaration
class PCB {
public:
struct {
string type;
linklist list; //refer to list which contains PCB instance
} status;
}
Or when you only refer to a type by reference or by pointer, you do not need to include it's header file.
linklist* list
You need to forward-declare each class before defining the other. In the header that defines PCB, write
class linklist;
before the definition of PCB, and in the header that defines linklist, write
class PCB;
before the definition of linklist. That way, when the compiler encounters each of the class definitions, it'll know that the "other" class's name is valid and let you declare pointers to it even though it hasn't been fully defined yet.
Edit: Sorry, I just noticed that your linklist::append function actually takes a PCB instance, not a pointer. In that case you need to make sure that the PCB class is defined before linklist, but you still need to forward-declare linklist before PCB so that you can make pointers to it. The order of your code should be:
class linklist;
class PCB {
// involves pointers to linklist
;
class linklist {
// holds instances of PCB
};
Edit Again: I's misread your **linklist list as a pointer to a linklist (even though it's syntactically wrong).
What you need to do is:
Forward-declare PCB so that the definition of linklist can refer to it in a method signature.
Define the linklist class, but not its append function yet.
Define the PCB class, which can contain an instance of linklist since that class is now fully-defined.
Define the linklist::append() function, which can take an instance of PCB since that class is now fully-defined.
That'll get your code to compile, but it won't do what you probably want it to, because the way you've defined your classes doesn't make much sense. Your PCB class doesn't "refer" to a list, it contains a list within it. Since that list member variable isn't a pointer, every PCB instance contains an entire linklist. When you append() a PCB to a linklist, you're making a copy of that whole PCB, including the (different) linklist that it contains.
I have a feeling you're coming from Java or C# and you're assuming that things are references when they really aren't. You need to learn about how to use pointers.
I am trying to implement a linked-list in C++. Currently, I have the following code:
using namespace std;
struct CarPart
{
int partNumber;
char partName[40];
double unitPrice;
CarPart* Next;
};
class ListOfParts
{
private:
int size;
CarPart* Head;
public:
ListOfParts():size(0), Head(NULL)
{
}
int Count()
{
return size;
}
};
Here the problem is, ideally, I should keep the Stuct CarPart within my Class. But I do not want to. At the same time, I don't want this to be acccessble anywhere from outside.
Can I have a some way, without creating a structure within the Class? Instead creating a new Class CarPart which could be accessible from only class ListOfPart?s
Well, as a first suggestion, have you considered using std::list? It would save you the trouble of implementing your own linked list semantics. Unless you're writing a linked list for the learning experience (which can be valuable), I suggest using:
struct CarPart
{
int partNumber;
std::string partName;
double unitPrice;
};
std::list<CarPart> ListOfParts;
You'll also notice I'm using std::string for text, which I suggest you use (unless you have a very good reason not to).
To the question at hand: you could declare the constructor for CarPart private, and then declare ListOfParts as a friend class, that's one way. But consider this: what do you gain by disallowing the construction of a car part external to the list of parts? I can't see that you gain anything. In fact, by using friends you introduce unnecessary complexity into the structure of your code - as using the dreaded 'friend' keyword usually does. Anyway, if you did want to use the friend class method, you would write:
class ListOfParts;
struct CarPart
{
friend class ListOfParts;
int partNumber;
char partName[40];
double unitPrice;
CarPart* Next;
private:
CarPart()
{
// Do nothing.
}
};
Which would mean only ListOfparts could call the default constructor for the list CarPart. Let me make this very clear: this is an abhorrent solution because it breaks rules of encapsulation. But, like mutable, friends have a use (and this isn't it).
What you're asking is contradictory. Either you want CarPart to be accessible from outside (in which case you declare it as a separate class or as a public member) or you don't want it accessible (in which case you declare it as a private member).
Consider making your class a little more generic: instead of having it be a linked list of CarParts, make it a class template that makes a linked list of Nodes that each has a T. If you are allowed to, you should be using std::list anyway, but you could write your own if you had to/really wanted to.
Also, classes and structs are basically the same thing; the only difference is that class members and inheritance are by default private, and struct members and inheritance are by default public. (The keywords are not always interchangeable, though.)
You can move your CarPart struct to a separate header and include this header only in the ListOfParts implementation part (yes, you need to separate definitions from implementations).
And don't forget a forward declaration
struct CarPart
before defining
class ListOfParts
I'm trying to teach myself C++, and one of the traditional "new language" exercises I've always used is to implement some data structure, like a binary tree or a linked list. In Java, this was relatively simple: I could define some class Node that maintained an instance variable Object data, so that someone could store any kind of object in every node of the list or tree. (Later I worked on modifying this using generics; that's not what this question is about.)
I can't find a similar, idiomatic C++ way of storing "any type of object." In C I'd use a void pointer; the same thing works for C++, obviously, but then I run into problems when I construct an instance of std::string and try to store it into the list/tree (something about an invalid cast from std::string& to void*). Is there such a way? Does C++ have an equivalent to Java's Object (or Objective-C's NSObject)?
Bonus question: If it doesn't, and I need to keep using void pointers, what's the "right" way to store a std::string into a void*? I stumbled upon static_cast<char*>(str.c_str()), but that seems kind of verbose for what I'm trying to do. Is there a better way?
C++ does not have a base object that all objects inherit from, unlike Java. The usual approach for what you want to do would be to use templates. All the containers in the standard C++ library use this approach.
Unlike Java, C++ does not rely on polymorphism/inheritance to implement generic containers. In Java, all objects inherit from Object, and so any class can be inserted into a container that takes an Object. C++ templates, however, are compile time constructs that instruct the compiler to actually generate a different class for each type you use. So, for example, if you have:
template <typename T>
class MyContainer { ... };
You can then create a MyContainer that takes std::string objects, and another MyContainer that takes ints.
MyContainer<std::string> stringContainer;
stringContainer.insert("Blah");
MyContainer<int> intContainer;
intContainer.insert(3342);
You can take a look at boost::any class. It is type safe, you can put it into standard collections and you don't need to link with any library, the class is implemented in header file.
It allows you to write code like this:
#include <list>
#include <boost/any.hpp>
typedef std::list<boost::any> collection_type;
void foo()
{
collection_type coll;
coll.push_back(boost::any(10));
coll.push_back(boost::any("test"));
coll.push_back(boost::any(1.1));
}
Full documentation is here: http://www.boost.org/doc/libs/1_40_0/doc/html/any.html
What you are looking for are templates. They allow you to make classes and function which allow you to take any datatype whatsoever.
Templates are the static way to do this. They behave like Java and C# generics but are 100% static (compile time). If you d'ont need to store different types of objetcs in the same container, use this (other answers describe this very well).
However, if you need to store different types of objects in the same container, you can do it the dynamic way, by storing pointers on a base class. Of course, you have to define your own objects hierarchy, since there is no such "Object" class in C++ :
#include <list>
class Animal {
public:
virtual ~Animal() {}
};
class Dog : public Animal {
public:
virtual ~Dog() {}
};
class Cat : public Animal {
public:
virtual ~Cat() {}
};
int main() {
std::list<Animal*> l;
l.push_back(new Dog);
l.push_back(new Cat);
for (std::list<Animal*>::iterator i = l.begin(); i!= l.end(); ++i)
delete *i;
l.clear();
return 0;
}
A smart pointer is easier to use. Example with boost::smart_ptr:
std::list< boost::smart_ptr<Animal> > List;
List.push_back(boost::smart_ptr<Animal>(new Dog));
List.push_back(boost::smart_ptr<Animal>(new Cat));
List.clear(); // automatically call delete on each stored pointer
You should be able to cast a void* into a string* using standard C-style casts. Remember that a reference is not treated like a pointer when used, it's treated like a normal object. So if you're passing a value by reference to a function, you still have to de-refrence it to get its address.
However, as others have said, a better way to do this is with templates
static_cast<char*>(str.c_str())
looks odd to me. str.c_str() retrieves the C-like string, but with type const char *, and to convert to char * you'd normally use const_cast<char *>(str.c_str()). Except that that's not good to do, since you'd be meddling with the internals of a string. Are you sure you didn't get a warning on that?
You should be able to use static_cast<void *>(&str). The error message you got suggests to me that you got something else wrong, so if you could post the code we could look at it. (The data type std::string& is a reference to a string, not a pointer to one, so the error message is correct. What I don't know is how you got a reference instead of a pointer.)
And, yes, this is verbose. It's intended to be. Casting is usually considered a bad smell in a C++ program, and Stroustrup wanted casts to be easy to find. As has been discussed in other answers, the right way to build a data structure of arbitrary base type is by using templates, not casts and pointers.