Sign in to follow this  
programering

Trying to code pure valid C++

Recommended Posts

I am trying to code my game in pure C++ style. But this is what gets me stuck; In C++ is the idea to use class'es. I want(ed) to use my CBitmaps class but it doesn't go because of the/my object definition. I always insist to have definitions as struct's, like this:
struct sObjectDef
{
	sBitmaps  *m_pBmps;	// dynamic array of bitmap structs.
	Uint8	   m_nBmps;	// the amount of bitmap structs of the above array.
	sSequence *m_pSeqs;	// dynamic array of sequence structs.
	Uint8	   m_nSeqs;	// the amount of sequence structs of the above array.
};

Structures with no functions, just data members. Therefore I can't use the CBitmaps class. Or if I make definition a class, like this:
class CObjectDef
{
public:
	CObjectDef(char *nameID);
	std::string m_strNameID;
	std::vector<CBitmaps *> m_vecBmps;
	std::vector<CSequence *> m_vecSeqs;
};

With vectors and then I can have it in class'es. So I don't know if I should have the object definitions as struct's or if everything in pure C++ shall be classes. When should one use struct's or classes? When should one use std::vector's or dynamic arrays? And one more thing should I have the constructor/function parameters char *pointer, std::string or std::string& reference. How is the most valid C++ coding manner way of doing it? It's things like this which gets me stuck and holds me from getting any results done, please help.

Share this post


Link to post
Share on other sites
Quote:

When should one use struct's or classes?


struct and class are almost the same thing in C++. A struct can have member functions, constructors and destructors just like a class. The main difference is that in a struct everything is public by default and in a class everything is private. Other than that, structs default to public inheritance and classes default to private.

Some people prefer to use struct for small POD types. But its just personal preference.

Quote:

When should one use std::vector's or dynamic arrays?


I assume "dynamic arrays" refers to raw new [] and delete []. Always use std::vector.

Quote:

And one more thing should I have the constructor/function parameters char *pointer, std::string or std::string& reference. How is the most valid C++ coding manner way of doing it?


In C++ we use std::string to represent text. std::string is a complex object, so we prefer to pass it by const reference rather than by value. So const std::string ¶meter.

Share this post


Link to post
Share on other sites
Quote:

Original post by programering
When should one use structs or classes?


The only difference between classes and structs is that the default visibility for structs is public and for classes it's private. Both can have c'tors/d'tors, member functions, access specifiers, etc.

Quote:
When should one use std::vector's or dynamic arrays?


In general, vectors are a better choice (and before you ask, no they are not slower that arrays).

Quote:
should I have the constructor/function parameters char *pointer, std::string or std::string& reference.


Again, in general, std::string is the better choice. As far as parameter passing conventions, prefer passing by const reference whenever possible.

This site has explanations regarding the reasoning for the above arguments, as well as a lot of other useful information.

Share this post


Link to post
Share on other sites
Quote:
Original post by programering
What do you think, shall I use struct or class as definition? What would be most valid the C++ standard?


Do you understand the differences as I have laid them out? They *are* the only differences. Its purely a style thing, since most people like to be explicit about public and private members anyway. If you just want an answer I would say use 'class', because privacy is a good thing.

Share this post


Link to post
Share on other sites
Quote:
Original post by rip-off
If you just want an answer I would say use 'class', because privacy is a good thing.

But the object class must have access to it's definitions. That's why I have the object definitions. You know the things about why you have definitions right? How would you have done it?

class CObjectDef
{
public:
CObjectDef(char *nameID);
std::string m_strNameID;
std::vector<CBitmaps *> m_vecBmps;
std::vector<CSequence *> m_vecSeqs;
};


class CObject
{
public:
CObject(int x, int y, Uint8 def);
void Update(void);
void Draw(short x, short y);
private:
Uint8 m_dir;
sPosition m_pos;
CBitmap *m_pBmp;
};



Share this post


Link to post
Share on other sites
Since you're interested in writing idiomatic C++, I'll point out a couple of things:
// This is a bit subjective, but I'd argue that there's no reason
// to prefix your class names with 'C'.
class CObjectDef
{
public:
// I'd make this argument a std::string (constant reference, of course),
// rather than a char*. That way you can submit either a char* or a
// string object.
CObjectDef(char *nameID);

// There's no need to encode the variable type in the name. For example,
// this should just be m_nameID, not m_strNameID.
std::string m_strNameID;

// That's especially true here, since you might choose to change the
// container type at a later date (e.g. to a list). These should really
// just be m_bmps and m_seqs (or better yet, m_bitmaps and m_sequences).

// Also, this is a good place to use typedefs, e.g.:

// typedef std::vector<CBitmaps *> bitmaps_t;

// bitmaps_t m_bitmaps;

// Finally, these containers should probably store smart pointers rather
// than raw pointers, but we won't go into that here.
std::vector<CBitmaps *> m_vecBmps;
std::vector<CSequence *> m_vecSeqs;
};


class CObject
{
public:
CObject(int x, int y, Uint8 def);
// In C++ we typically don't use 'void' to indicate an empty argument
// list; just leave the parentheses empty (e.g. void Update()).
void Update(void);
void Draw(short x, short y);
private:
// Is Uint8 from SDL? For portability purposes I'd just use an int,
// or, if you really want a particular number of bits, use a typedef
// from the Boost 'stdint' header (can't remember exactly what it's
// called).
Uint8 m_dir;
sPosition m_pos;
CBitmap *m_pBmp;
};
Now after all that, I have to admit that I'm not sure I understand the actual question that you're asking, so perhaps you could clarify it a bit.

Share this post


Link to post
Share on other sites
Quote:
Original post by programering
You know the things about why you have definitions right?

Class definitions? Yes.
Definitions in the sense that you seem to be talking about them? Not really - enlighten us.

It's not clear what you're trying to achieve here.
I think the problem is you're not really using terminology particularly well and it's somewhat confusing.

Quote:
With vectors and then I can have it in class'es.

So I don't know if I should have the object definitions as struct's or if everything
in pure C++ shall be classes.

You can have vectors in structs, you can have methods too. You seem to think that structs are somehow not 'pure' C++? They're part of the language for sure.

Quote:
When should one use struct's or classes?

It's purely stylistic. Most people are accustomed to reading class, however some people (like myself) may use structs for POD types.

Quote:
When should one use std::vector's or dynamic arrays?

This is an example of poor terminology usage, a std::vector is practically always a dynamic array implementation. We assume that when you say 'dynamic array' you mean using new[] and delete[]. The answer is use std::vector always [smile]

Quote:
And one more thing should I have the constructor/function parameters char *pointer, std::string or std::string& reference.

Prefere to pass strings by a constant reference, so that's: const std::string&

Quote:
How is the most valid C++ coding manner way of doing it?

No such thing as 'most valid', they're all equally just as valid, some ways are just better practice.

If style is viciously impeding on getting things done then most programmers tend to opt for what works first and foremost; then they worry about how to make it better.

Share this post


Link to post
Share on other sites
It sounds like you are striving for the One True Method of programming C++. pure? its "pure" if your not using any other languages inside the code. (no including cstdio, you must use std, and so on) Valid? if it compiles its valid. No warning allowed.

Thats it, really.

Share this post


Link to post
Share on other sites
Quote:
Original post by shotgunnutter
It sounds like you are striving for the One True Method of programming C++. pure? its "pure" if your not using any other languages inside the code. (no including cstdio, you must use std, and so on) Valid? if it compiles its valid. No warning allowed.

Thats it, really.
I'm interpreting 'pure' as meaning 'idiomatic' in the context of the OP's post. But, I could be wrong in that interpretation...

Share this post


Link to post
Share on other sites
Quote:
Original post by dmatter
If style is viciously impeding on getting things done then most programmers tend to opt for what works first and foremost; then they worry about how to make it better.

That's the kind of things which gets me stuck. I have difficulties to decide if should class or struct, pointer array or vector in the object definitions.

And I thought my identifier prefixes was the standard, e.g. Hungary notation.

Share this post


Link to post
Share on other sites
Quote:
Original post by dmatter
Class definitions? Yes.
Definitions in the sense that you seem to be talking about them? Not really - enlighten us.

It's not clear what you're trying to achieve here.
I think the problem is you're not really using terminology particularly well and it's somewhat confusing.

I don't mean class definitions, I mean object definitions you know in games; As monster definitions as an example, first you load the monster definitions which are the different types of monsters defined, then in your monster object(class or struct) decide which monster type definition you want that instance to be.
I mean object definitions as in game elements.

As you can see I have very hard to formulate me well.

Share this post


Link to post
Share on other sites
Quote:
That's the kind of things which gets me stuck. I have difficulties to decide if should class or struct, pointer array or vector in the object definitions.
As you become more familiar with C++ and programming idioms, as well as gain experience, you will have less trouble making such decisions.

Quote:
And I thought my identifier prefixes was the standard, e.g. Hungary notation.
There is no standard. In reality, there are a number of good sense rules and guidelines, as well as common idioms that other C++ programmers recognize.
Hungarian notation is a recognized idiom. It is not good sense though. It’s a blight really, as the naming scheme it suggests does not help human readers. Hungarian notation was created to indicate clearly the type of something. It’s effectively useless in my book. As a programmer, your biggest problem is figuring out the *purpose* of something. If you have trouble figuring out whether something is an int or a C string or a class, then it’s not the naming convention that is in trouble. Either your programming language of choice has some serious underlying problems, or you simply don’t know the language.

Share this post


Link to post
Share on other sites
Quote:
Original post by programering
Quote:
Original post by dmatter
If style is viciously impeding on getting things done then most programmers tend to opt for what works first and foremost; then they worry about how to make it better.

That's the kind of things which gets me stuck. I have difficulties to decide if should class or struct, pointer array or vector in the object definitions.

We'll there are no hard and fast rules, it's entirely up to you whether to use class or struct, in the end a struct is a class.
Here's the rules of thumb I use:

If its going to have: methods (incl. constructor or destructor), private or protected data, or in someway require inheritance - then use a class.

If not, then it's only going to contain public data, if this is actually meant to represent only data (state) then I use a struct, otherwise I'm doing something more complicated and it depends on exactly what I'm doing.

Quote:
And I thought my identifier prefixes was the standard, e.g. Hungary notation.

It's not the standard, it's just a convention. The actual standard C++ library doesn't use that convention, I don't use that convention and neither does jyk.
I use a convention known as CamelCase:
UpperCamelCaseForClassNames
lowerCamelCaseForMethods()
lowerComelCaseForVariables
BUT_ALL_CAPS_SEPARATED_BY_UNDERSCORES_FOR_CONSTANTS.


Quote:
I don't mean class definitions, I mean object definitions you know in games; As monster definitions as an example, first you load the monster definitions which are the different types of monsters defined, then in your monster object(class or struct) decide which monster type definition you want that instance to be.
I mean object definitions as in game elements.

Ah, I understand now [smile]

What you may want to look into are some creational design patterns, like the abstract factory, factory method, builder and prototype patterns. Found a good link.

Choosing the subjectively 'best' method does sort of depend on how you want to interface with this system and how many entites you might have, with what sort of control you want/need.
Based on the code you've presented so far, you seem to want to be able to create different types of entities from a single object description; so one way you might want to tackle this could be as so:

You have a structure that can fully describe how to initialise an entity instance:

struct EntityDescriptor
{
std::string name;
std::vector<Bitmap*> bitmaps;
std::vector<Sequence*> sequences;
EntityController* controller;
/*
Anything else here
*/

};

N.B. You might want to consider using smart pointers or references instead of raw pointers, otherwise you need to decide who owns the actual instances.

Now you also have an entity class that can construct itself from a description by taking the attributes it's interested in:

class Entity
{
public:
// Take whatever attributes we care about for construction.
Entity(const EntityDescriptor& desc);

void update();
void render();

private:
std::string name;
Bitmap image;
EntityController& controller;

vector2D position;
float angle;
// etc
};

Entity::Entity(const EntityDescriptor& desc)
{
name = desc.name; // copy the name
image = desc.bitmaps[ 0 ]; // take the 1st bitmap
controller = *desc.controller; // take the controller
position = controller.getStartPosition(); // take the start position
angle = controller.getStartOrientation(); // take the start angle
}


Then you have a factory that can create actual scene entities.
Here's a simple one (with no error checking), it stores prototypes of EntityDescriptors and when an entity needs to be created it finds the suitable description and passes that to the entity's constructor:

class EntityFactory
{
public:
// Adds a description of an entity to the factory.
void addEntityDescriptor(const EntityDescriptor& desc);

// Creates and returns a new entity instance.
Entity* create(const std::string name);

private:
std::map<std::string, EntityDescriptor> entityDescriptions;
};


void EntityFactory::addEntityDesctiptor(const EntityDescription& desc)
{
entityDescriptions[desc.name] = desc;
}

Entity* EntityFactory::create(const std::string name)
{
// Pass the description to the entity's constructor (should validate that 'name' actually exists in the map.)
return new Entity( entityDescriptions[name] );
}


So with all that in-place you can now add descriptors of entities to a factory at load-time and then whenver you want to spawn an entity you can ask the factory to find a suitable descriptor and construct an entity using it...


// Load the different entities that make up the game (probably from an external game file, but i've used hard-coded constants here)
void Game::loadEntityDescriptors()
{
this->entityFactory.addEntityDescriptor( Game::PLAYER_DESC );
this->entityFactory.addEntityDescriptor( Game::GHOST_DESC );
this->entityFactory.addEntityDescriptor( Game::TREE_DESC );
this->entityFactory.addEntityDescriptor( Game::WATER_DESC );

//
// Create a forest description
//

// Take the generic tree descriptor as a starting point
EntityDescriptor forestDesc = Game::TREE_DESC;
// Replace the tree controller with a forest controller
forestDesc.controller = &this->forestController;
// Change the name
forstDesc.name = "Forest";
// The density of trees in the forest
this->forestController.setTreeDensity(10);
// Add to the factory
this->entityFactory.addEntityDescriptor( forestDesc );
}

// Create a forest
void Game::spawnForest()
{
this->forestController.randomiseSpawnPoint();
this->entityPool.add( this.entityFactory.create("Forest") );
}



Well there you go. Hopefully that gives you some ideas.

One other thing worth mentioning - with the configuration of entities, their logic (the controllers) and their representation (bitmaps), you can look into the Model-View-Controller (MVC) idiom. The code I presented above is based on the snippets you provided, better use of the MVC pattern can lead to a cleaner and more flexible design overall [smile]

[Edited by - dmatter on January 1, 2008 6:27:05 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by oler1s
Quote:
That's the kind of things which gets me stuck. I have difficulties to decide if should class or struct, pointer array or vector in the object definitions.
As you become more familiar with C++ and programming idioms, as well as gain experience, you will have less trouble making such decisions.


There. Best answer so far IMHO.

Oler1s, browse some other's c++ code and see how they wrote their code. Then you'll have some references on how things can be done. If you have doubts about why someone made something in a specific way, come here and ask.
There are lots of Open Source games written in C++ that you can download the source code.

Share this post


Link to post
Share on other sites
Quote:
Oler1s, browse some other's c++ code and see how they wrote their code.
You sure you got the right person there? ;)
Quote:
That is the thing about hungarian notation most people got it wrong.
People may have misunderstood the purpose or implementation of HN. However, even “correctly” implemented, it still pushes bad code.

This is the fundamental idea HN pushes: you have a variable that needs to encode information about what context it should be used in. Since you can freely choose the name of the variable, name it in such a way that this extra information is evident. For the sake of brevity, come up with some abbreviations to tack on as a prefix to each variable, to indicate the context to be used in.

But there’s something fundamentally wrong about this approach. If for example, you have two strings, one containing unchecked user data and one containing checked data, you should not be manually naming each string to reflect what it should contain. It’s unmaintainable, bad design. What if you switch third party libraries; the new one guarantees incoming user data to be valid and safe. Are you going to go around renaming all your variables? The other way around? Besides, your code starts looking like machine generated code with all the prefixes.

No. If you are forced to play name games with variables to write good code, then your language has fundamental problems. Early C had problems. Modern C++ has features and idioms to properly deal with the need to indicate information about the variable. But you know what relying on HN does? Aside from writing bad code, you don’t bother to take advantage of the tools available to you. Tools that make your life and other programmers’ who have to read your code, much better.
This is precisely why I warn beginners in C++ to stay away from HN and similar notations.

Share this post


Link to post
Share on other sites
Initializer lists!

Instead of:
Entity::Entity(const EntityDescriptor& desc)
{
name = desc.name; // copy the name
image = desc.bitmaps[ 0 ]; // take the 1st bitmap
controller = desc.controller; // take the controller
position = controller.getStartPosition(); // take the start position
angle = controller.getStartOrientation(); // take the start angle
}


do:

Entity::Entity(const EntityDescriptor& desc)
: name( desc.name ); // copy the name
, image( desc.bitmaps[0] ); // take the 1st bitmap
, controller( desc.controller ); // take the controller
, position( controller.getStartPosition() ); // take the start position
, angle( controller.getStartOrientation() ); // take the start angle
{
}


While it remains arguable about which is better, there is a certain aspect that initializer lists cover, namely const variables.

Consider this:
class Foo {
Foo( const std::string & s ) : name( s ) {}

Foo( const Foo & other ) : name( other.name ) {}

Foo operator=( const Foo &other ) {
return Foo(other);
}
const std::string s;
};


It's impossible to such things with assignments, since assignment operator doesn't work on const variables.

Share this post


Link to post
Share on other sites
Now I got loose, now I know how I shall do.

But I have encountered this error I don't know how to deal with about string reference parameter:

game.cpp
f:\projects\programming\klingis entertainment\klingis 2d\sdl - 1 sprite\pure c++\game.cpp(24) :
error C2664: '__thiscall CFile::CFile(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &)' :
cannot convert parameter 1 from 'char [9]' to 'class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &'
A reference that is not to 'const' cannot be bound to a non-lvalue


In:

CFile *pFile = new CFile("heil.bmp"); // <-- THIS LINE !!!


The CFile constructor declarations:

CFile(std::string &rFilename);



This is what I have written now, the file source code: "filesrc.h"

#ifndef _FILESRC_H
#define _FILESRC_H





void InitDir();




enum FILEDIR
{
FILEDIR_APP,
FILEDIR_DATA,
FILEDIR_MAPS,
FILEDIR_FONTS,
FILEDIR_TILES,
FILEDIR_TEXTURES,
FILEDIR_SCREENS,
FILEDIR_ENTITIES,
FILEDIR_SOUNDS,
FILEDIR_MUSIC,
FILEDIR_SAVES,
NUM_FILEDIRS
};


#include <string>


class CFileDir
{
public:
CFileDir(std::string &rName, FILEDIR parent);
static std::string &GetDirPath(FILEDIR dir);
private:
static CFileDir **s_pFileDirs;
static std::string s_dirpath;
std::string m_name;
FILEDIR m_parent;
};




class CFile
{
public:
CFile(std::string &rFilename);
bool SetDir(FILEDIR dir);
void SetDir(std::string &rDirname);
void AddDir(std::string &rDirname);
SDL_RWops *Open(char *mode);
SDL_RWops *Open(std::string &rFilepath, char *mode);
SDL_RWops *GetRWops();
void Close();
~CFile();
private:
// FILEDIR m_filedir
std::string m_filename;
std::string m_dirpath;
std::string m_filepath;
SDL_RWops *m_pRWops;
};





#endif




"filesrc.cpp"

#include "filesrc.h"



CFileDir *g_pFileDirs[NUM_FILEDIRS];


void InitDir()
{
g_pFileDirs[FILEDIR_APP] = NULL;
g_pFileDirs[FILEDIR_DATA] = new CFileDir("../../../Data",FILEDIR_APP );
g_pFileDirs[FILEDIR_MAPS ] = new CFileDir("Maps" ,FILEDIR_APP );
g_pFileDirs[FILEDIR_FONTS ] = new CFileDir("Fonts" ,FILEDIR_DATA);
g_pFileDirs[FILEDIR_TILES ] = new CFileDir("Tiles" ,FILEDIR_DATA);
g_pFileDirs[FILEDIR_TEXTURES] = new CFileDir("Textures" ,FILEDIR_DATA);
g_pFileDirs[FILEDIR_SCREENS ] = new CFileDir("Screens" ,FILEDIR_DATA);
g_pFileDirs[FILEDIR_ENTITIES] = new CFileDir("Entities" ,FILEDIR_DATA);
g_pFileDirs[FILEDIR_SOUNDS ] = new CFileDir("Sounds" ,FILEDIR_DATA);
g_pFileDirs[FILEDIR_MUSIC ] = new CFileDir("Music" ,FILEDIR_DATA);
g_pFileDirs[FILEDIR_SAVES] = new CFileDir("Saves" ,FILEDIR_DATA);

CFileDir::s_pFileDirs = g_pFileDirs;
}





CFileDir::CFileDir(std::string &rName, FILEDIR parent)
{
m_name = rName;
m_parent = parent;
};



CFileDir **CFileDir::s_pFileDirs;
std::string CFileDir::s_dirpath;


std::string &CFileDir::GetDirPath(FILEDIR dir)
{
CFileDir *pFileDir = s_pFileDirs[dir];
s_dirpath = "";

while (pFileDir)
{
FILEDIR parent = pFileDir->m_parent;

// if (parent < NUM_FILEDIRS)
// {
s_dirpath += pFileDir->m_name + '/';
pFileDir = s_pFileDirs[parent];
// }
}

return s_dirpath;
}






CFile::CFile(std::string &rFilename)
{
m_filename = rFilename;
// m_directory = FILEDIR_APP;
m_dirpath = new std::string;
}


bool CFile::SetDir(FILEDIR dir)
{
m_dirpath = CFileDir::GetDirPath(dir);
}


void CFile::SetDir(std::string &rDirname)
{
m_dirpath = rDirname + '/';
}


void CFile::AddDir(std::string &rDirname)
{
m_dirpath += rDirname + '/';
}



SDL_RWops *CFile::Open(char *mode)
{
m_filepath = m_dirpath + m_filename;

return Open(m_filepath,mode);
}



SDL_RWops *CFile::Open(std::string &rFilepath, char *mode)
{
fprintf(stdout,"Opening file: \"%s\"\n",rFilepath);
m_pFile = SDL_RWFromFile(rFilepath,mode);

return GetRWops();
}



SDL_RWops *CFile::GetRWops()
{
return pRWops;
}



void CFile::Close()
{
SDL_RWclose(pRWops);
}



~CFile::CFile()
{
Close();
SDL_FreeRW(pRWops);
}







I'll get rid off that hungary notation in a later version.


And that's real nice demonstrations, dmatter. By the way are you the author of Dark Matter?

Share this post


Link to post
Share on other sites
Quote:
Original post by Antheus
Initializer lists!

....

While it remains arguable about which is better

Absolutely! I do apologise.
Certainly they offer no advantage in this particular situation, but initialiser lists are no doubt better [grin]

Quote:
Original post by programering
The CFile constructor declarations:

CFile(std::string &rFilename);

Pass const references: const std::string& filename

Quote:

And that's real nice demonstrations, dmatter. By the way are you the author of Dark Matter?

You're welcome. But no, I'm not the author; at the risk of sounding naive, I don't know what Dark Matter is, I assume it's a novel.

Share this post


Link to post
Share on other sites
Quote:
Original post by stonemetal
That is the thing about hungarian notation most people got it wrong. Here is an interesting article explaining how to do it right.
http://www.joelonsoftware.com/articles/Wrong.html


In his specific example, making two new classes equivalent to the first (possibly publically derived from it) with an explicit conversion that does that for you would be leagues better as it would handle the conversion itself. Code shouldn't just "look wrong", if something is always wrong you should be prevented to write it. It's a bit orwellian but in this case it's justified - if you can't write invalid code that is vulnerable (or wrong), you won't. If somebody really really wants to he'll have to use even much more wrong constructs or seek help from somebody - who would be well able to explain why it's forbidden and what to do instead.

Prefixes aren't your friend, they're your warts. The compiler is your friend - let him do the dirty work.

Share this post


Link to post
Share on other sites
Quote:
Original post by dascandy
The compiler is your friend - let him do the dirty work.


Because that's what friends are for, right? [grin]

Seriously though, well said.

Share this post


Link to post
Share on other sites
Just thought I'd chip in with my 2p here regarding the classes / struct's discussion.

For me the right time to use a struct is when I want to map out some memory. Most commonly I use C-style structures when I'm doing low-level memory handling with pure pointers and it's more important to me to see the size / layout of the memory than writing an API abstraction. Off the top of my head some common situations where I feel this is necessary are when dealing with file io and network packets.

Often when I want the object to perform some processing on its data or perform otherwise non-trivial interactions with other objects I promote the object to a class.

Although it is possible to code an API which will hide much of the low-level interaction with memory and thus mostly avoid the C-style approach to memory handling, I prefer to hide these things from other programmers but not from myself.

Finally, when it is unavoidable that an unknown quantity of memory has to be thrown around I use a utility class which wraps the memory in an object and using C++ template functions it provides a simpler API for reading / writing the memory.

Share this post


Link to post
Share on other sites
Maybe this is just me, but I generally prefer const char* over const std::string&. The reason is I can pass either a const char* or a std::string (vis c_str()) without needing to contruct a string object in the former case. Since a lot of the time all that's done with the string is to assign it to a member std::string or a simple comparison, it seems pointless to dynamically allocate a new string to hold a non-changing copy.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this