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
Related
I need to represent a tree hierarchy (an AST to be precise) in my C++ program. Ok, I saw examples of such structures many times, but one thing stays unclear to me. Please, tell me why it is so common to use classes instead of structs for an AST in C++? For example, consider this code, that represents a node of an AST:
class Comparison {
public:
Node* getLhs() const { return m_lhs; }
Node* getRhs() const { return m_rhs; }
//other stuff
private:
ComparisonOperator m_op;
Node* m_lhs;
Node* m_rhs;
};
(it is inspired by https://github.com/clever-lang/clever/blob/master/core/ast.h#L150 but I have thrown away some unnecessary details)
As you see here we have two getters which return pointers to private data members and those pointers even aren't const! As I heard that breaks encapsulation. So why not structs (in which all members are public by default) for AST nodes? How would you implement an AST in C++ (I mean dealing with accessibility issue)?
I personally think that structs are suit well for such tasks.
I posted code from an arbitrary project, but you may see this practice (classes with encapsulation breaking methods for ASTs) is rather often.
Please, tell me why it is so common to use classes instead of structs for an AST in C++? [..] I personally think that structs are suit well for such tasks.
It doesn't matter; C++ doesn't have structs†. When you write struct, you're creating a class.
Either write struct or write class. Then either write public or write private.
Some people choose class, because they think that classes defined using struct cannot contain private members, member functions and so on. They are wrong.
Some people choose class, because they just prefer to keep struct behind for "simple" types with no private members or member functions, purely for style reasons. That's subjective and entirely up to them. (I mostly do a similar thing myself.)
† The standard does use the term "structs" and "a struct" in a very small handful of places, sometimes apparently as a shortcut for referring to POD classes, but other times in error (e.g. C++14 §C.1.2/3.3 "a struct is a class"). This has led some people to question the fact that C++ does not have structs (including suggesting that "structs" are a subset of classes, although this notion is not well-enough defined to be formally accepted). Regardless, the behaviour of the std::is_class trait makes things pretty clear.
Well, consider this code:
class Parent {
public:
int x;
void test();
private:
int y;
};
class Child : public Parent {
public:
int z;
};
Now the same thing with the struct keyword:
struct Parent {
int x;
void test();
private:
int y;
};
struct Child : Parent {
int z;
};
Some prefer the class keyword to make clear that something is a class, and struct for some data only classes
Maybe something like the following would be an acceptable pattern?
class Comparison {
public:
const Node* lhs() const { return m_lhs; }
const Node* rhs() const { return m_rhs; }
Node* mutable_lhs() const { return m_lhs; }
Node* mutable_rhs() const { return m_rhs; }
//other stuff
private:
ComparisonOperator m_op;
Node* m_lhs;
Node* m_rhs;
};
If the programmer intends to get a node that is mutable, then at least he makes his intention clear?
BTW even with mutable_lhs() he only gets pointer to a mutable node, but he still doesn't get to change the pointer itself. He would lose that protection if using struct without explicit public/private specification.
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.
Can someone please point me towards some nice resources for understanding and using nested classes? I have some material like Programming Principles and things like this IBM Knowledge Center - Nested Classes
But I'm still having trouble understanding their purpose. Could someone please help me?
Nested classes are cool for hiding implementation details.
List:
class List
{
public:
List(): head(nullptr), tail(nullptr) {}
private:
class Node
{
public:
int data;
Node* next;
Node* prev;
};
private:
Node* head;
Node* tail;
};
Here I don't want to expose Node as other people may decide to use the class and that would hinder me from updating my class as anything exposed is part of the public API and must be maintained forever. By making the class private, I not only hide the implementation I am also saying this is mine and I may change it at any time so you can not use it.
Look at std::list or std::map they all contain hidden classes (or do they?). The point is they may or may not, but because the implementation is private and hidden the builders of the STL were able to update the code without affecting how you used the code, or leaving a lot of old baggage laying around the STL because they need to maintain backwards compatibility with some fool who decided they wanted to use the Node class that was hidden inside list.
Nested classes are just like regular classes, but:
they have additional access restriction (as all definitions inside a class definition do),
they don't pollute the given namespace, e.g. global namespace. If you feel that class B is so deeply connected to class A, but the objects of A and B are not necessarily related, then you might want the class B to be only accessible via scoping the A class (it would be referred to as A::Class).
Some examples:
Publicly nesting class to put it in a scope of relevant class
Assume you want to have a class SomeSpecificCollection which would aggregate objects of class Element. You can then either:
declare two classes: SomeSpecificCollection and Element - bad, because the name "Element" is general enough in order to cause a possible name clash
introduce a namespace someSpecificCollection and declare classes someSpecificCollection::Collection and someSpecificCollection::Element. No risk of name clash, but can it get any more verbose?
declare two global classes SomeSpecificCollection and SomeSpecificCollectionElement - which has minor drawbacks, but is probably OK.
declare global class SomeSpecificCollection and class Element as its nested class. Then:
you don't risk any name clashes as Element is not in the global namespace,
in implementation of SomeSpecificCollection you refer to just Element, and everywhere else as SomeSpecificCollection::Element - which looks +- the same as 3., but more clear
it gets plain simple that it's "an element of a specific collection", not "a specific element of a collection"
it is visible that SomeSpecificCollection is also a class.
In my opinion, the last variant is definitely the most intuitive and hence best design.
Let me stress - It's not a big difference from making two global classes with more verbose names. It just a tiny little detail, but imho it makes the code more clear.
Introducing another scope inside a class scope
This is especially useful for introducing typedefs or enums. I'll just post a code example here:
class Product {
public:
enum ProductType {
FANCY, AWESOME, USEFUL
};
enum ProductBoxType {
BOX, BAG, CRATE
};
Product(ProductType t, ProductBoxType b, String name);
// the rest of the class: fields, methods
};
One then will call:
Product p(Product::FANCY, Product::BOX);
But when looking at code completion proposals for Product::, one will often get all the possible enum values (BOX, FANCY, CRATE) listed and it's easy to make a mistake here (C++0x's strongly typed enums kind of solve that, but never mind).
But if you introduce additional scope for those enums using nested classes, things could look like:
class Product {
public:
struct ProductType {
enum Enum { FANCY, AWESOME, USEFUL };
};
struct ProductBoxType {
enum Enum { BOX, BAG, CRATE };
};
Product(ProductType::Enum t, ProductBoxType::Enum b, String name);
// the rest of the class: fields, methods
};
Then the call looks like:
Product p(Product::ProductType::FANCY, Product::ProductBoxType::BOX);
Then by typing Product::ProductType:: in an IDE, one will get only the enums from the desired scope suggested. This also reduces the risk of making a mistake.
Of course this may not be needed for small classes, but if one has a lot of enums, then it makes things easier for the client programmers.
In the same way, you could "organise" a big bunch of typedefs in a template, if you ever had the need to. It's a useful pattern sometimes.
The PIMPL idiom
The PIMPL (short for Pointer to IMPLementation) is an idiom useful to remove the implementation details of a class from the header. This reduces the need of recompiling classes depending on the class' header whenever the "implementation" part of the header changes.
It's usually implemented using a nested class:
X.h:
class X {
public:
X();
virtual ~X();
void publicInterface();
void publicInterface2();
private:
struct Impl;
std::unique_ptr<Impl> impl;
}
X.cpp:
#include "X.h"
#include <windows.h>
struct X::Impl {
HWND hWnd; // this field is a part of the class, but no need to include windows.h in header
// all private fields, methods go here
void privateMethod(HWND wnd);
void privateMethod();
};
X::X() : impl(new Impl()) {
// ...
}
// and the rest of definitions go here
This is particularly useful if the full class definition needs the definition of types from some external library which has a heavy or just ugly header file (take WinAPI). If you use PIMPL, then you can enclose any WinAPI-specific functionality only in .cpp and never include it in .h.
I don't use nested classes much, but I do use them now and then. Especially when I define some kind of data type, and I then want to define a STL functor designed for that data type.
For example, consider a generic Field class that has an ID number, a type code and a field name. If I want to search a vector of these Fields by either ID number or name, I might construct a functor to do so:
class Field
{
public:
unsigned id_;
string name_;
unsigned type_;
class match : public std::unary_function<bool, Field>
{
public:
match(const string& name) : name_(name), has_name_(true) {};
match(unsigned id) : id_(id), has_id_(true) {};
bool operator()(const Field& rhs) const
{
bool ret = true;
if( ret && has_id_ ) ret = id_ == rhs.id_;
if( ret && has_name_ ) ret = name_ == rhs.name_;
return ret;
};
private:
unsigned id_;
bool has_id_;
string name_;
bool has_name_;
};
};
Then code that needs to search for these Fields can use the match scoped within the Field class itself:
vector<Field>::const_iterator it = find_if(fields.begin(), fields.end(), Field::match("FieldName"));
One can implement a Builder pattern with nested class. Especially in C++, personally I find it semantically cleaner. For example:
class Product{
public:
class Builder;
}
class Product::Builder {
// Builder Implementation
}
Rather than:
class Product {}
class ProductBuilder {}
I think the main purpose of making a class to be nested instead of just a friend class is the ability to inherit nested class within derived one. Friendship is not inherited in C++.
You also can think about first class ass type of main function, where You initiate all needed classes to work togheter. Like for example class Game, initiate all other classes like windows, heroes, enemy's, levels and so on. This way You can get rid all that stuff from main function it self. Where You can create obiect of Game, and maybe do some extra external call not related to Gemente it self.
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;
};
I'm having some toubt here. Hope you guys can share out some programming tips. Just curious to know whether is it a good programming practice if I do something like the code below.
class Outer {
public:
class Inner {
public:
Inner() {}
}
Outer() {}
};
I have been doing this for structure where I only want my structure to be expose to my class instead of global. But the case is different here, I am using a class now? Have you guys facing such a situation before? Very much appreciated on any advice from you ;)
I'll break the answer into two parts:
for cases where you only organize code, you should use namespaces instead of classes -- if the inner class isn't an entity that is only worked with from inside the class (especially only constructed in the class), then inner classes are a good idea -- another example STL function objects.
in C++ there is absolutely NO DIFFERENCE between structures and classes except that structures have public members by default. Hence there's no real difference when you have classes -- it's more a matter of style.
This is a good practice in many cases. Here's one where we implement a link list:
template <class T>
class MyLinkList {
public:
class Node {
public:
Node* next;
T data;
Node(const T& data, Node* node) : next(node), data(data) {}
};
class Iterator {
public:
Node* current;
Iterator(Node* node) : current(node) {}
T& operator*() { return current->data; }
void operator++(int) { current = current->next; }
bool operator!=(int) { return current != NULL; }
};
private:
Node* head;
}
The above is just snippet that is not intended to be complete or compilable. The point is to show that Node and Iterator are inner classes to the MyLinkList class. The reason why this makes sense is to convey the fact that Node and Iterator are not independent to be stand alone by themselves, but they need to be qualified by MyLinkList (for instance MyLinkList::Iterator it)
This is purely a matter of style, however I think it is typically more common in the C++ community to use a namespace named detail for classes that are purely helpers or are purely used in the implementation of other classes. There are several advantages to using namespaces in place of inner classes, among them include: greater compatibility (how compilers resolve names in inner classes can be incredibly different between Visual C++ and GCC, for example), more encapsulation (in the inner/outer variant, the inner class has greater access to members of instances of the outer class), easier implementation (you don't have to fully qualify the helper class every single time in the implementation file, since you can put a using directive in the ".cpp" source file). If you are going to use an inner class, then you need to make the conscious decision to make that a part of your API.
Using Namespaces
namespace collection
{
namespace detail
{
class LinkedListNode
{
//...
};
}
class LinkedList
{
// ...
};
}
Using Inner Classes
namespace collection
{
class LinkedList
{
// ...
class LinkedListNode
{
// ...
};
// ...
};
}
It's not an everyday thing, but it's not unheard of, either. You would do this if there were a class (Inner) that only makes sense to a client program when the client is using Outer.
If you only want a class to be exposed in a certain file, you can use an unnamed namespace within that file. Then whatever code is within that namespace is only available within that file.
namespace
{
//stuff
}