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.
Related
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.
What should I know about having two separate classes in one .h file?
I have a binary search tree class with all the members and public & private functions.
class BinarySearchTree
{
struct Node {
Node* left;
Node* right;
int val;
};
};
and following that code I want to design a stack of pointers to that binary search tree node. Within the same.h file I have
class stack
{
Node* array;
//
};
Visual Studio doesn't show linkage and doesn't recognize Node*. Is it ok to declare two separate classes in one .h file or is it better to implement the stack class nested inside the binary search tree class?
You've declared a struct called Node that is nested in the class BinarySearchTree, so if you want to refer to that struct outside of the class, you need to refer to it like this:
class stack
{
BinarySearchTree::Node* array;
//
};
Whether or not that's good design is a whole new question, so I would recommend getting a bit further with the implementation before asking more.
EDIT
Like you noticed, it's necessary to make the nested struct public if you want to use it outside of the class. That, in itself, is not necessarily bad or wrong. You're not exposing data, just a declaration.
You've got two choices:
Make the nested struct public.
Take the nested struct outside of the enclosing class.
Personally, I'd go for the first option.
Say I have two different objects that are completely different, Sprite and PhysicsData.
I write an empty base class and a container class that can push and remove objects to/from a container.
I create two of these containers to store the two different objects - Sprite and PhysicsData.
(Different objects aren't together in the same class)
class base
{
};
class ContainerManager
{
public:
std::vector<base*> list;
void Push(base *object);
void Remove(base *object);
};
class PhysicsData : public base
{
void applyGravity();
};
class Sprite : public base
{
void Draw();
};
ContainerManager SpriteContainer;
ContainerManager PhysicsDataContainer;
Sprite aSprite;
SpriteContainer.Push(&aSprite);
PhysicsData SomeData;
PhysicsDataContainer.Push(&SomeData);
Is this the way that this should bet done?
This is not a C++ way. You should use templates.
For you to know, STL (which you are calling to when using std:: namespace prefix) is, actually, Standard Template Library :). A lot of template classes are already there, e.g. for the push / remove operations see std::list<T>
You use it like this:
std::list<Sprite> SpriteContainer;
std::list<PhysicsData> PhysicsDataContainer;
and so on.
There is a cool guide about C++ templates, if you still want to do your own class for some more functionality.
And there is a reference to std::list, (i don't think i need to explain the usage of std::vector for you) if the question was the actual thing you've wanted to do.
You're having Templates in C++ and still worrying about having a common base class for a trivial container??
template <class T>
class Container{
private:
vector<T> list;
public:
void Push(T data);
T Pop();
};
If you put a single virtual function into the base class, you'll be able to use dynamic_cast to get back the proper pointer if you mix different types in the same container. A virtual destructor would be a good idea because then you could delete the object if it were dynamically allocated, without having to cast it back to the original pointer.
If you're not going to mix types within a single container, I agree with dreamzor that a template class would be better. That's the way all the standard containers are implemented.
That looks like technically correct code but you are not doing any type checking. So as you can see PhysicsData is showing up in your SpriteContainer. You probably do not want this.
There is more than one way to keep PhysicsData out of your SpriteContainer. One way is to use templates. With templates you would state what type of base objects the container should work with at compile time.
Another method is to inherit from your ContainerManager two types of ContainerManagers, one called PhysicsContainerManager and one called SpriteContainerManager. These two child classes can do type check to verify that the objects being passed are in fact either a SpriteContainer or a PhisicsData. This link shows how to do type check in c++ C++ equivalent of instanceof
thanks
jose
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 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;
};