|
Will,
There's nothing technically wrong with your code. MyClass contains a public vector vPtrOC, which is a vector or pointers to otherClass objects. These objects in turn contain a public vector vOC_str each.
Nothing wrong here; myClass can access all otherClass items pointed to be the vPtrOC vector, and for each of these access the darn string vector.
I suspect there is an error in your approach; obviously you suffer from some problem, but neither problem nor reason is evendent in your code snippet.
Besides, you might want to consider your programming style. Public data members, vectors of pointers to objects under (presumably) foreign memory management, unconviencing naming policy, that is all the stuff progammers' hell is made from - including your own, if you revisit that code in a few months.
I recommend Bruce Eckel.
Bernd
|
|
|
|
|
Thanks for replying.
Sometimes it is difficult to pose a question, as it is to answer it, and perhaps I may not have written the question in as clear a manner for others to understand.
I was not implying that the sample code the question showed, is illegal code. It is not illegal code, therefore I know I am able (by the rules of C++) to access the vector of strings from MyClass. The question sought to discern an optimal way someone might go about doing it. In all honesty, I have been able to access the vector in question; it's just that my way seemed more awkward than optimal, and wanted to obtain a more efficient style.
I think I'll settle on the 'for_each()' algorithm.
William
Fortes in fide et opere!
|
|
|
|
|
Will,
Don't settle for the for_each algorithm. Settle for Bruce Eckel's "Thinking in C++".
It is the most reasonable book on C++ programming I ever came across (and there were many), and he doesn't waste time explaining the zeroes and the ones. And: it's free (mind you reading 1500 pages on the screen can be hard work).
Bernd
|
|
|
|
|
Let me see if I have this right: I asked an STL question, and the answer you are offering me, is for me to go read a book (or at least those portions of the book that pertain to my question).
Other than me having acknowledged that I have already found a way for doing what I wanted (albeit an awkward way), the emphasis behind the question was more on finding a better way of accomplishing it.
If every time I want to check to see if somebody may have found a better way of doing something (realizing I have to contend with certain limitations in life: "time" being one of them, and the fact I will not know everything in this world ), that I would be better off to go read portions of a book (or several books), then why ask questions in the first place? Why ask ANY question, any at all? Might as well, we keep reading portions of a whole bunch of books every time we have a question, and remove the alternative of interfacing with peers and a place like CodeProject!!!
The whole reason why a place like CodeProject exist, is for developers to have a meeting place where they can gather and meet with their peers (in cyber space) to bring and trade solutions, ideas, tips, questions and everything else relating to technical matters (and some).
If the CodeProject Community were to (individually) go off reading portions of books every time someone needed to find out something, there wouldn't be a need for a place like CodeProject!!
William
Fortes in fide et opere!
|
|
|
|
|
Your response is completely out of order. I certainly regret having upset you so much, though.
I did not misunderstand your question. My answer is "read this book" - Bruce collected a lot of useful advise that does relate to your question, and I see no reason why I should re-type his 1500 well-written pages here.
You don't seem to cope with frank advise, and mistake it for insult. If that's the way you read it, then so be it.
So, returning to your question:
a) you should not expose public data members
b) you should implement suitable verbs where possible, and accessors/mutators where needed
c) you should re-consider your naming policy
d) you should re-consider your referencing stratey (consider using references or smart pointers)
These are a lot of architectural weaknesses for an 8-liner, don't you think?
I think I might have mentioned a good book that details this much better than I could...
Bernd <grin>
|
|
|
|
|
First of all, I am not upset! I took your response and analyzed it for what it portrayed.
I am well aware that certain data should NOT be public. It makes good sense to me (for simplicity and ease of development) to make data public at first, and then when the program is working well, to go back and clean things up before releasing it to production. (It's my style, and it works well for me. Getting a program to work first is more important to me, followed by cleaning up and complying with conventions.)
"for_each()" is an STL algorithm. I had nothing to do with it being that name, and as far as having a "naming policy" goes, that is rather subjective, though I try to make mine as descriptive as possible (for what I'm doing).
With regards to whether a smart pointer is more suitable for what I'm doing, I believe it's a judgement call on my side. I am not overly eager to show people how things can be done by using esoteric tools as smart pointers. There is a time and a place for everything, and smart pointers will be the tool of the day when the time and the place call for it. Right now for what I'm doing, I believe it can be accomplished without the need for smart pointers.
On the matter of using "references", I mostly use them for passing data as parameters. Other than that, I prefer to deal with pointers. (Again it's my style, and may you live happily with yours.)
For a miniscule piece of code that was posted, I am amazed that you have taken to reading so much from it, with total absence to the remaining portion of the program relative to the tiny role this piece plays.
William
Fortes in fide et opere!
|
|
|
|
|
WREY wrote:
It makes good sense to me (for simplicity and ease of development) to make data public at first, and then when the program is working well, to go back and clean things up before releasing it to production. (It's my style, and it works well for me.
Biiiig mistake. This works while you have are studying. When you do programming for a living - the moment it runs, it will not be changed anymore. There are deadlines to meet, there are testing issues involved. How many bugs do you introduce when you "clean up" your code?
Do it right from the beginning. It saves your job. Believe me. And better get familiar to it before your boss asks you to do it.
Finally moved to Brazil
|
|
|
|
|
There is such a thing as "signing off" on a project. The time to check over EVERYTHING you've done, is BEFORE you release the program to production. If you didn't understand that it is then (before releasing it to production) would be when you do your 'double checkings', I'm sorry if I didn't make that clear. I don't believe anybody who does programming for a living, need be told that the time to 'double check' their work, would be BEFORE "signing off" on it.
The whole idea of 'double checking' your work, is NOT to introduce more bugs (even though I wonder whether some people actually believe that). For me it is to make certain that everything works, that it works according to specifications, and that I can personally say to the people whose going to be using it, that "It works, and it works BETTER than when you last used it!!"
If you don't feel you can say those words when you are signing off on your project, then "YES," you are in the wrong business, and it wouldn't be too long before you find yourself talking to who employed you.
Suddenly this post has turned from STL to someone's personal style. I don't intend to continue with it any further because my style is "my style"; it works for me, and may others be happy with their's. The one thing I will NOT do, is to follow what OTHERS might say (even if I don't feel it's right for me), but do it anyway because THEY think it is what I should do.
I follow the directions of those who are paying me (even after I've given them the benefit of my opinion), and for those other times when doing something is not feasible or legal, I do what I believe is right, and "Take responsibility for my own actions!!"
William
Fortes in fide et opere!
|
|
|
|
|
WREY wrote:
The time to check over EVERYTHING you've done, is BEFORE you release the program to production.
Which is not quite what you said before. You was talking about changing it after you made sure it works. I was just adding my 2 cents to that.
WREY wrote:
Suddenly this post has turned from STL to someone's personal style. I don't intend to continue with it any further because my style is "my style";
Why not? People may still benefit from this discussion. After all, "your style" is made up of other peoples knowledge, style and wisdom (as is mine). Thats just normal. When you learn somthing you are bound to your teacher. You may improve on it, but seldom get around it, for good or for bad.
cheers
Leon[^] - Enterprise Anti-Spam Server
|
|
|
|
|
Hi, everyone
I meet some problem when I try to use the sort algo in STL to sort a structure that contains pointers. I am sure I have define the proper copy constructor to avoid memory disorder. However, it seems that the sort function disorder the memory. Could you give some advice on it? The following is the test code:
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <cstdlib>
#include <cstdio>
#include <sys types.h="">
using namespace std;
struct str_info
{
string content;
size_t occ_sum;
long * occ_pos; // occurrence
public:
str_info(): content(""), occ_sum(0),occ_pos(NULL){}
~str_info() { if (occ_pos != NULL) delete[] occ_pos; occ_pos = NULL; }
str_info(const str_info& info){
content = info.content;
occ_sum = info.occ_sum;
occ_pos = new long[occ_sum+1];
memcpy(occ_pos, info.occ_pos, sizeof(long)*occ_sum);
}
};
class cmp_str_info
{
public :
int operator()(const str_info& info1, const str_info& info2) const
{
return strcmp(info1.content.c_str(), info2.content.c_str()) < 0;
}
};
void init(str_info * info)
{
info[0].content = "info0";
info[0].occ_sum = 1;
info[0].occ_pos = new long[info[0].occ_sum];
info[0].occ_pos[0] = 45;
info[1].content = "a_info1";
info[1].occ_sum = 1;
info[1].occ_pos = new long[info[1].occ_sum];
info[1].occ_pos[0] = 55;
info[2].content = "b_info2";
info[2].occ_sum = 1;
info[2].occ_pos = new long[info[2].occ_sum];
info[2].occ_pos[0] = 35;
}
int main()
{
vector<str_info> vstr;
vstr.clear();
str_info info[3];
init(info);
vstr.push_back(info[0]);
vstr.push_back(info[1]);
vstr.push_back(info[2]);
vector<str_info>::iterator it;
cout<<"Before sorting....\n";
for (it = vstr.begin(); it != vstr.end(); it++)
{
cout<<it->content<<" "<<it->occ_pos[0]<<endl;
}
str_info *="" infos="new" str_info[3];
infos[0]="
sort(vstr.begin()," vstr.end(),="" cmp_str_info());
cout<<"\nafter="" sorting...\n";
for="" (it="vstr.begin();" it="" !="vstr.end();" it++)
{
cout<<it-="">content<<" "<<it->occ_pos[0]<
|
|
|
|
|
For the way that you defined your struct str_info, you also need to implement operator=.
However, I would suggest that you use a vector as the occ_pos member, and don't bother with either the copy constructor or assignment operator. If all the members of your str_info struct support assignment and copy constructor, you won't need to implement these.
Best regards,
John
|
|
|
|
|
How do I get this is in WTL? I have tried looking for something similar to AfxGetInstanceHandle() but can find anything???
Cheers
The word of the day is legs, let's go back to my house and spread the word
|
|
|
|
|
|
I remember reading somewhere that WTL does not destroy an object that is attached to it. Does this mean when I attach an HIMAGELIST to a CImageList using Attach() and that CImageList object goes out of scope I have to manually remove or delete the HIMAGELIST or destroy HWND or whatever?
The reason I ask I have two CImageList objects inside a class and both get initialized during WM_CREATE . However frequently, one of the CIMageList objects has to be re-created so what I do is
Detach() each CImageList object
Create image list from system image list
Attach() it to CImageList
Set the image list to control like Listview
In the destructor of my CListCtrl() should I destroy the objects HIMAGELIST?
Thanks
The word of the day is legs, let's go back to my house and spread the word
|
|
|
|
|
|
Thats what I thought, but does this mean then that the HIMAGELIST handle is left floating around?
Wouldn't this waste or cause memory leaks of any kind or are these objects destroyed when your application ends?
I'm curious basically becuz I have 2 functions, one which initializes an CImageList by attaching it to the system HIMAGELIST returned by SHGetFileinfo , but before attaching I always do a Detach . I figure I would be a bad idea to Destroy() this image list? I do however Detach again in destructor. My second function doesn't use the system image list but rather initializes it with icons I have collected. So I Destroy , then Create and Destroy() again inside destructor.
In MFC I've always assumed that destructor took care of everything?
Thanks
The word of the day is legs, let's go back to my house and spread the word
|
|
|
|
|
Hockey wrote:
but does this mean then that the HIMAGELIST handle is left floating around?
Yes, but...
Hockey wrote:
Wouldn't this waste or cause memory leaks of any kind or are these objects destroyed when your application ends?
No, because when your process exits, all memory and resources it was using go away too (memory gets reclaimed by the OS). However, it's still good practice to not be sloppy, and properly free/destroy/delete resources in your cleanup code.
If you want a class that destroys the image list in the destructor, check out this page[^]
--Mike--
Ericahist | CP SearchBar v2.0.2 | Homepage | RightClick-Encrypt | 1ClickPicGrabber
Pinky, are you pondering what I'm pondering?
I think so Brain, but if we shaved our heads, we'd look like weasels!
|
|
|
|
|
although most WTL classes take care of releasing the object they manage (if they manage it), CImageList is a sore exception. I guess it is not an ideal world! Perhaps it is because imagelists have window semantics and as "windows" you need to destroy them manually
To answer your question, yes you should destroy all imagelists you create yourself, ideally at the moment you no longer require them. However the "system" imagelist returned by SHGetFileInfo is a shared resource which you needn't (shouldn't in 9x) destroy
most of the other WTL classes have a managed and unmanaged "flavor". E.g. you have CBitmap and CBitmapHandle; the first is managed, destroying the bitmap whenever it goes out of scope, the second is meant for temporary assignments.
|
|
|
|
|
I created a rich edit control with ES_MULTILINE | ES_WANTRETURN in CComCompositeControl dialog.
I am able to edit text but pressing Enter key has no effect.
|
|
|
|
|
I need to implement drag & drop feature support to composite control. My Composite Control contains Tree control and list view controls, i need to drag the list view control data and drop into the Tree view control. Please send me some samples and necessary information to implement the same.
|
|
|
|
|
Hi everybody
My problem related to ini file using map. i have solve this problem using vector.in vector i used two structures one for keys and second for section.i want to it compatible with map. i m confused to how insert section and its key using map. plz help me to solve this problem.
// st_key
// This structure stores the definition of a key. A key is a named identifier
// that is associated with a value. It may or may not have a comment. All comments
// must PRECEDE the key on the line in the config file.
//header file using vector
typedef struct st_key
{
t_Str szKey;
t_Str szValue;
t_Str szComment;
st_key()
{
szKey = t_Str("");
szValue = t_Str("");
szComment = t_Str("");
}
} t_Key;
typedef std::vector<t_key> KeyList;
typedef KeyList::iterator KeyItor;
// st_section
// This structure stores the definition of a section. A section contains any number
// of keys (see st_keys), and may or may not have a comment. Like keys, all
// comments must precede the section.
typedef struct st_section
{
t_Str szName;
t_Str szComment;
KeyList Keys;
st_section()
{
szName = t_Str("");
szComment = t_Str("");
Keys.clear();
}
} t_Section;
typedef std::vector<t_section> SectionList;
typedef SectionList::iterator SectionItor;
/// General Purpose Utility Functions ///////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
void Report(e_DebugLevel DebugLevel, char *fmt, ...);
t_Str GetNextWord(t_Str& CommandLine);
int CompareNoCase(t_Str str1, t_Str str2);
void Trim(t_Str& szStr);
int WriteLn(fstream& stream, char* fmt, ...);
/// Class Definitions ///////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
// CDataFile
class CDataFile
{
// Methods
public:
// Constructors & Destructors
/////////////////////////////////////////////////////////////////
CDataFile();
CDataFile(t_Str szFileName);
virtual ~CDataFile();
// File handling methods
/////////////////////////////////////////////////////////////////
bool Load(t_Str szFileName);
bool Save();
// Data handling methods
/////////////////////////////////////////////////////////////////
// GetValue: Our default access method. Returns the raw t_Str value
// Note that this returns keys specific to the given section only.
t_Str GetValue(t_Str szKey, t_Str szSection = t_Str(""));
// GetString: Returns the value as a t_Str
t_Str GetString(t_Str szKey, t_Str szSection = t_Str(""));
// GetFloat: Return the value as a float
float GetFloat(t_Str szKey, t_Str szSection = t_Str(""));
// GetInt: Return the value as an int
int GetInt(t_Str szKey, t_Str szSection = t_Str(""));
// GetBool: Return the value as a bool
bool GetBool(t_Str szKey, t_Str szSection = t_Str(""));
// SetValue: Sets the value of a given key. Will create the
// key if it is not found and AUTOCREATE_KEYS is active.
bool SetValue(t_Str szKey, t_Str szValue,
t_Str szComment = t_Str(""), t_Str szSection = t_Str(""));
// SetFloat: Sets the value of a given key. Will create the
// key if it is not found and AUTOCREATE_KEYS is active.
bool SetFloat(t_Str szKey, float fValue,
t_Str szComment = t_Str(""), t_Str szSection = t_Str(""));
// SetInt: Sets the value of a given key. Will create the
// key if it is not found and AUTOCREATE_KEYS is active.
bool SetInt(t_Str szKey, int nValue,
t_Str szComment = t_Str(""), t_Str szSection = t_Str(""));
// SetBool: Sets the value of a given key. Will create the
// key if it is not found and AUTOCREATE_KEYS is active.
bool SetBool(t_Str szKey, bool bValue,
t_Str szComment = t_Str(""), t_Str szSection = t_Str(""));
// Sets the comment for a given key.
bool SetKeyComment(t_Str szKey, t_Str szComment, t_Str szSection = t_Str(""));
// Sets the comment for a given section
bool SetSectionComment(t_Str szSection, t_Str szComment);
// DeleteKey: Deletes a given key from a specific section
bool DeleteKey(t_Str szKey, t_Str szFromSection = t_Str(""));
// DeleteSection: Deletes a given section.
bool DeleteSection(t_Str szSection);
// Key/Section handling methods
/////////////////////////////////////////////////////////////////
// CreateKey: Creates a new key in the requested section. The
// Section will be created if it does not exist and the
// AUTOCREATE_SECTIONS bit is set.
bool CreateKey(t_Str szKey, t_Str szValue,
t_Str szComment = t_Str(""), t_Str szSection = t_Str(""));
// CreateSection: Creates the new section if it does not allready
// exist. Section is created with no keys.
bool CreateSection(t_Str szSection, t_Str szComment = t_Str(""));
// CreateSection: Creates the new section if it does not allready
// exist, and copies the keys passed into it into the new section.
bool CreateSection(t_Str szSection, t_Str szComment, KeyList Keys);
// Utility Methods
/////////////////////////////////////////////////////////////////
// SectionCount: Returns the number of valid sections in the database.
int SectionCount();
// KeyCount: Returns the total number of keys, across all sections.
int KeyCount();
// Clear: Initializes the member variables to their default states
void Clear();
// SetFileName: For use when creating the object by hand
// initializes the file name so that it can be later saved.
void SetFileName(t_Str szFileName);
// CommentStr
// Parses a string into a proper comment token/comment.
t_Str CommentStr(t_Str szComment);
protected:
// GetKey: Returns the requested key (if found) from the requested
// Section. Returns NULL otherwise.
t_Key* GetKey(t_Str szKey, t_Str szSection);
// GetSection: Returns the requested section (if found), NULL otherwise.
t_Section* GetSection(t_Str szSection);
// Data
public:
t_Section* GetSectionName( t_Str SectionName);
long m_Flags; // Our settings flags.
protected:
SectionList m_Sections; // Our list of sections
t_Str m_szFileName; // The filename to write to
bool m_bDirty; // Tracks whether or not data has changed.
};
thanks
fefgfgfgfgfg
|
|
|
|
|
Hi:
I´m trying to use WTL in an AX control. With previous ATL version you just needed to change CComModule to CAppModule. But now that CComModule was splitted this doesn´t work anymore.
What else should i change???
Thanks
Gabriel
Old C programmers never die. They just cast into void
|
|
|
|
|
I have a class like this that wraps the webbrowser
template <typename T><br />
class IEHost : public IDispEventSimpleImpl<1, IEHost<T>, &__uuidof(DWebBrowserEvents2)><br />
{<br />
...<br />
BEGIN_SINK_MAP(IEHost)<br />
SINK_ENTRY_INFO(1, __uuidof(DWebBrowserEvents2), 259, DocumentComplete, &DocumentCompleteInfo)<br />
SINK_ENTRY_INFO(1, __uuidof(DWebBrowserEvents2), 250, BeforeNavigate2, &BeforeNavigate2Info)<br />
SINK_ENTRY_INFO(1, __uuidof(DWebBrowserEvents2), 102, StatusTextChange, &StatusTextChangeInfo)<br />
END_SINK_MAP()<br />
...<br />
}
And an atl dialog class that uses it
class StartDlg : public CAxDialogImpl<StartDlg> ,<br />
public CStrDlg<StartDlg>,<br />
public CDialogResize<StartDlg>,<br />
public IEHost<StartDlg><br />
{<br />
}
This compiled fine with VC6, but with VC7
i get this error.
I tried all i can think of to get it to compile but with no luck.
Anyone knows how to get it to work in VC7
c:\Program Files\Microsoft Visual Studio .NET\Vc7\atlmfc\include\atlcom.h(4016): error C2440: 'initializing' : cannot convert from 'const ATL::_ATL_EVENT_ENTRY<T> *' to 'const ATL::_ATL_EVENT_ENTRY<T> *'<br />
with<br />
[<br />
T=IEHost<StartDlg><br />
]<br />
and<br />
[<br />
T=StartDlg<br />
]
/Magnus
- I don't necessarily agree with everything I say
|
|
|
|
|
Don't know, I don't have all info, but just wild shot - try:
<br />
template <typename T><br />
class IEHost : public IDispEventSimpleImpl<1, T, &__uuidof(DWebBrowserEvents2)><br />
{<br />
...<br />
BEGIN_SINK_MAP(T)<br />
...<br />
}<br />
Then it should at least compile
|
|
|
|
|
No, dont compile then either, i get 21 errors on the BEGIN_SINK_MAP/SINK_ENTRY_INFO macros.
Tried changing those params every way that seems somewhat resonable with no luck.
/Magnus
- I don't necessarily agree with everything I say
|
|
|
|
|