|
Christian Graus wrote:
Stroustrup says use of macros usually indicates a bad programmer or a bad design. I guess this proves him right.....
Yes I've read his book. But for my case, I code a set of single code for two kinds of different machines, I have to do with it:
in declaration:
#if MACHINE == TYPE_A
CMyStack m_ctrlStk[10];
#elif MACHINE == TYPE_B
CMyStack m_ctrlStk[3];
#endif
in .cpp:
#if MACHINE == TYPE_A
for(i = 0; i < 10; i++)
#elif MACHINE == TYPE_B
for(i = 0; i < 3; i++)
#endif
{
m_ctrlStk[i].Morph();
}
Maxwell Chen
Lets make bugs better!
|
|
|
|
|
See, I would just use a vector.
Christian
The tragedy of cyberspace - that so much can travel so far, and yet mean so little.
And you don't spend much time with the opposite sex working day and night, unless the pizza delivery person happens to be young, cute, single and female. I can assure you, I've consumed more than a programmer's allotment of pizza, and these conditions have never aligned. - Christopher Duncan - 18/04/2002
|
|
|
|
|
Just like the #ifdef _AFXDLL trick in VC++,
#ifdef _AFXDLL
InitXXX();
#else
InitXXXStatic();
#endif
In my case, even the I/O of the machines are different. Thus:
enum _IoAddress {
#if MACHINE == 1
enACSwitch = 0x001,
enRelayMaster = 0x018 // and many many other I/O addresses..
#elif MACHINE == 2
enACSwitch = 0x093,
enRelayMaster = 0x071
#endif
};
Then I can code once, benefitted everywhere:
PLC_SetOutput(enACSwitch, bPowerOn);
PLC_SetFlag(enRelayMaster, bPause);
// ......
Maxwell Chen
Lets make bugs better!
|
|
|
|
|
Stroustrup says a lot of things that I don't agree with. This being one of them.
Tim Smith
I know what you're thinking punk, you're thinking did he spell check this document? Well, to tell you the truth I kinda forgot myself in all this excitement. But being this here's CodeProject, the most powerful forums in the world and would blow your head clean off, you've got to ask yourself one question, Do I feel lucky? Well do ya punk?
|
|
|
|
|
I avoid using it as much as possible, but do you think that it is ever useful and that it has its uses?
For example, the SAFE_RELEASE macro for COM interfaces:
#define SAFE_RELEASE(ptr) if(ptr) {(ptr)->Release(); ptr = NULL;}
Have you ever found any uses for macros, for some reason or another, C++ code would just not be a good solution?
Build a man a fire, and he will be warm for a day Light a man on fire, and he will be warm for the rest of his life!
|
|
|
|
|
kilowatt wrote:
For example, the SAFE_RELEASE macro for COM interfaces:
Any macro that takes a variable is suspect, and a debugging nightmare.
kilowatt wrote:
Have you ever found any uses for macros, for some reason or another, C++ code would just not be a good solution?
At work I've written some common code as macros after much argument for an inline function. Personally I've used them in one project, a debugging tool where a macro was the only option, because it is able to report the file name and line number in which the trace command was written. A function obviously would not expand in place and therefore not work as I would desire.
Christian
The tragedy of cyberspace - that so much can travel so far, and yet mean so little.
And you don't spend much time with the opposite sex working day and night, unless the pizza delivery person happens to be young, cute, single and female. I can assure you, I've consumed more than a programmer's allotment of pizza, and these conditions have never aligned. - Christopher Duncan - 18/04/2002
|
|
|
|
|
Christian Graus wrote:
Any macro that takes a variable is suspect, and a debugging nightmare.
You are definitely right about that. Debugging can be a nightmare, especially when you have a macro that spans across a couple of lines.
In a code generator that I wrote, we use a macro to properly thunk the Ansi/unicode conversions which helped make the generated code more readable and since no one was supposed to edit those files by hand, we felt fairly safe using the macros there. However, the debugging of the macro was a little difficult, we usually resorted to cut and paste (which sucked!)
Build a man a fire, and he will be warm for a day Light a man on fire, and he will be warm for the rest of his life!
|
|
|
|
|
kilowatt wrote:
For example, the SAFE_RELEASE macro for COM interfaces:
Use smart pointers instead. Most of the time there are alternatives and where an alternative exists like using inline functions etc there is no excuse for using preprocessor. My 2c
|
|
|
|
|
Christian Graus wrote:
The preprocessor is evil, avoid it if you can.
Evil?
Let's say you are using VC6, since VC7 isn't really in that widespread use, then the only way to fix some bugs in Microsoft's "interpretation" of the C++ language is to use the preprocessor (f.ex. the age-old #define for if(0){}else for ). Anything that helps fix Microsoft bugs must surely be not from the dark side.
It's also the only way you can:
- do portable include file protection
- implement
assert
- stringize a (type-) name
- Select the right library to link with automagically, especially when you have got six different possible CRT models (single-threaded, multi-threaded, multithreaded using CRT from DLL, and then debug and release versions of these three)
- ...
There is of course ways to use the preprocessor for the purposes of the dark side, MFC message maps comes to mind, but say the language feature that can't be misused.
/Mike In the hands of the wrong person, even see-hash can be dangerous... I think...
|
|
|
|
|
Mike Nordell wrote:
do portable include file protection
That much is true.
Mike Nordell wrote:
implement assert
Wrong. The std library provides assert, there is no need to impliment it yourself.
Mike Nordell wrote:
stringize a (type-) name
True. When would you want to do this, except in a debug tool, which I've already said I have done myself using macros ?
Mike Nordell wrote:
There is of course ways to use the preprocessor for the purposes of the dark side, MFC message maps comes to mind, but say the language feature that can't be misused.
True. Now list the language features that Stroustrup says are usually a sign of bad design or bad programming. I use macros, sparingly. I find a lot of people over-use them and usually they should take the advice of the person who wrote the language, and use const variables and inline functions instead.
Christian
The tragedy of cyberspace - that so much can travel so far, and yet mean so little.
And you don't spend much time with the opposite sex working day and night, unless the pizza delivery person happens to be young, cute, single and female. I can assure you, I've consumed more than a programmer's allotment of pizza, and these conditions have never aligned. - Christopher Duncan - 18/04/2002
|
|
|
|
|
Christian Graus wrote:
Wrong. The std library provides assert, there is no need to impliment it yourself.
However true that statement is, I'm not wrong. The only way one can implement assert is by using the preprocessor (macro facility).
stringize a (type-) name
True. When would you want to do this, except in a debug tool, which I've already said I have done myself using macros ?
I've used it in a few places where I need the stringized typename to create factories.
Now list the language features that Stroustrup says are usually a sign of bad design or bad programming.
Ehhh, macros?
I find a lot of people over-use them and usually they should take the advice of the person who wrote the language, and use const variables and inline functions instead.
The last years I've experienced a decline in the use of macros, and more and more I've seen templates, integral constants and inline functions used.
Unfortunately the (probably) most widely used header files on the planet makes our lives problematic if we try to name something e.g. SendMessage .
|
|
|
|
|
Christian Graus wrote:
Rule #2: See Rule #1.
That is the best way to state it.
But there are places where they are valuable
1. Adding __LINE__, __FILE__ tracing information in the code.
stuff like,
#define MYTRACE(x) TraceF(__FILE_, __LINE__, x);
2. #ifdef DEBUG stuff is usefule
These are the only two places where I ever use preprocessor.
I hate code where I see stuff like
#define _NOIMPL_ STDMETHOD(QueryInterface)(REFIID , void**) \
{ \
return E_NOTIMPL; \
}
|
|
|
|
|
Read MSDN
Best regards,
Alexandru Savescu
|
|
|
|
|
I've made a menu using a Window, but i need to know how to get the icons from the toolbars.
|
|
|
|
|
You mean you want to add icons to the toolbar, don't you?
Nish
Regards,
Nish
Native CPian.
Born and brought up on CP.
With the CP blood in him.
|
|
|
|
|
Not To the toolbar, i only want to get the icons from the toolbar to draw it to my menu, a bitmapped fakemenu.
|
|
|
|
|
I am a new user in Visual C++. I have tried calling complex numbers in the usual C++ way. That is by:
#include <complex>
#include <iostream>
using namespace std;
int main()
{
complex<float> a( 3.0, 4.0 );
cout << "Real: " << a.real() << " Image: " << a.imag() << endl;
complex<float> b( 6.0, 7.0 );
a = a + b;
cout << "Real: " << a.real() << " Image: " << a.imag() << endl;
return 0;
}
This works perfectly in the conventional programming, but if I try to call complex types in class function (the OOP way). The compiler don't recognise this type. Why is this so? How should i try to get around this problem?
I have notice a complex template class in VC++ also. Could I use this ? And how should I do it? I am not familiar with template class.
|
|
|
|
|
You must to include the math.h header
Plus the name od the struct that you need is called _complex ..
This struct is composed by the real component X abnd imaginary Y
struct _complex num = {8.0, 1.0};
double real = num.x;
double imaginary = num.y;
Best Regards
Carlos Antollini.
www.wanakostudios.com
Sonork ID 100.10529 cantollini
|
|
|
|
|
Thanks for the reply, Carlos. I really appreciate it!
I have tried that out. SO any idea how I could manipulate this
num with operators? I have tried to do this
num = num * 2;
This doesn't work.., this is the complier error.
error C2676: binary '*' : 'struct _complex' does not define this operator or a conversion to a type acceptable to the predefined operator
I need to declare every single operator function? It's there a short cut?
|
|
|
|
|
This works perfectly in the conventional programming, but if I try to call complex types in class function (the OOP way). The compiler don't recognise this type.
Could you please elaborate? If the compiler don't recognize the type it means you haven't include the header file <complex>.
I have notice a complex template class in VC++ also. Could I use this ?
Ehhh, are you kidding? You just used it in your example.
|
|
|
|
|
Well, maybe I didn't quite put it through correctly. I was trying to say that I was able to use that in the conventional way. I was having problem in VC++ 6.0. I was trying to access the complex type in class function. When I tried to put
#include <complex>
.
.
void trest::tesin(int a)
{
complex<float> abc;
}
the complier will report a error with complex<float>, it's not a recognised as a type. I am trying to access this complex type.
|
|
|
|
|
complex (as most standard things) is inside namespace std.
|
|
|
|
|
Thanks, I really miss that line in the program.I could access this
type now in the class function.
void trest::tesin(complex<float> a)
{
complex<float> b;
b = b * b;
}
I am trying to use it in the class function declaration part. The complier scream again for error.
rest.h(11) : error C2871: 'std' : does not exist or is not a namespace
trest.h(16) : error C2061: syntax error : identifier 'complex'
trest.cpp(30) : error C2511: 'tesin' : overloaded member function 'void (class std::complex<float>)' not found in 'trest'
trest.h(13) : see declaration of 'trest'
|
|
|
|
|
Hey, got my problems solved! Just a few missing lines from the original codes. Thanks for all your help guys!
Cheers,
Danny
|
|
|
|
|
I use ACCESS file as my database,but when I add a record into it,it throw error as follow:
invalid character or specs (NULL).
what cause this error occured? and how to solve it?
(I use MFC ODBC )
the program code as follow:
sqltext.Format ("select * from example");
pRS->Open (AFX_DB_USE_DEFAULT_TYPE,sqltext,CRecordset::dynamic);
pRS->AddNew();
//开始读文件
long length=filedata.GetLength ();
HGLOBAL hData=GlobalAlloc(GHND,length);
pRS->m_filename=filename;
pRS->m_filelength=length;
pRS->m_filedata.m_dwDataLength=length;
pRS->m_filedata.m_hData=GlobalLock(hData);
filedata.ReadHuge (pRS->m_filedata.m_hData,length);
pRS->SetFieldDirty (&pRS->m_filedata);
pRS->SetFieldNull (&pRS->m_filedata,FALSE);
pRS->Update ();
pRS->Close ();
GlobalUnlock(hData);
GlobalFree(hData);
filedata.Close ();
Don't look at me in that way!
|
|
|
|
|