|
Regarding the symbol name, it is just a convention to use something that resembles the file name, for readability. It is always capitalized to avoid name collisions - language keywords are never all capitals, and #defines and typedefs are never named after files.
--Mike--
Latest blog entry: *drool* (Alyson) [May 10]
Ericahist | Homepage | RightClick-Encrypt | 1ClickPicGrabber
"You have Erica on the brain" - Jon Sagara to me
|
|
|
|
|
Capitalisation does not avoid name collisions. Example:
_DEBUG
The compiler defines _DEBUG when you specify the /MTd or /Mdd option. These options specify debug versions of the C runtime library.
Use GUID or MS-specific #pragma once.
|
|
|
|
|
1.) If Classes in C++ can do anything Structs do plus
more, why do we still have Structs in C++? Is there
something Classes can't do but Structs? Do you
prefer Classes over Structs?
2.) I understand the difference between Classes and
Structs is the default asscess of the Structs is public,
and Classes is private. But I don't understand why do we
use private. I know that the private keyword specifies
that those members are accessible only from member functions
and friends of the class. But why do we use it? Any specific
example? Why do we want to limit those asscess?
|
|
|
|
|
VW_Red_Jetta wrote:
why do we still have Structs in C++?
The reason is to maximise the compatibility with C. C has structs, and the default access level is public, so C++ retains the same system.
VW_Red_Jetta wrote:
But I don't understand why do we use private.
C++ additionally allows classes, and specifies that good encapsulation / good OOP the default access should be private. This ensures that anyone who needs to get/set the properties of a private variable will have to use an accessor or a mutator method. In general, you need to modify the properties of an object via getXXX() and setXXX() methods.
As a rule of thumb, use structs for POD, Plain Old Data (anything without pointers, that doesn't need initialisation or special procudures for copying). Use classes when you need to have your class DO something, rather than just store information.
|
|
|
|
|
[quote] As a rule of thumb, use structs for POD, Plain Old Data (anything without pointers, that doesn't need initialisation or special procudures for copying). Use classes when you need to have your class DO something, rather than just store information. [/quote]
Okay, so can we simply just use classes through all of the C++ programs?
Do the real world programmers use structs and classes together? Since
the existence of structs is for the backward compatibility of C language,
and Classes can do anything Structs do, so why not just use classes?
I second this question: Do the real world programmers use structs and classes together?
Thanks.
|
|
|
|
|
VW_Red_Jetta wrote:
I second this question: Do the real world programmers use structs and classes together?
Yes, look an any real API and you'll find some structs. Generally I try to avoid them, unless you're sending a very strong message about the complexity of the object.
DirectX for example.
In DirectX struct is used to signify that objects (especially the vertices of polygons) can be memcpy()'d directly. This is used almost to speed up the process of adding to the vertex buffer.
Not that I'd generally cite DirectX as a API for demonstrating good programming practices, but it's appropriate in this situation.
|
|
|
|
|
VW_Red_Jetta wrote:
Do the real world programmers use structs and classes together?
Yes, in fact I wrote two struct s today. Yes, you could use all classes, there is no rule against that. However for readability sake, I use a struct when it's just a group of data, with no methods outside of a constructor to init the data to 0 or some other default.
--Mike--
Latest blog entry: *drool* (Alyson) [May 10]
Ericahist | Homepage | RightClick-Encrypt | 1ClickPicGrabber
"You have Erica on the brain" - Jon Sagara to me
|
|
|
|
|
Hi,
Just wondering if anyone knows how to write a program which can automatically install a device driver(from .inf) file into the OS.
Thanks
|
|
|
|
|
I've got a datafile to read from a mainframe system.
It's got data store in the bits of each byte.
I want to be able to define a struct to extract the bits so I can optimize the bitshiting operations I have to do (It's a big file).
I can't find anything that shows how to define a struct to anything lower than a BYTE.
Please help.
typedef struct ffStockData
{
BYTE fBucketCount;
// I need to be able to expand this to 2 values per 1 byte
BYTE ffFiller[104];
} FFSTOCKDATA, *PFFSTOCKDATA;
|
|
|
|
|
// Try this:
#include "stdafx.h"
struct Bits
{
unsigned m_1stBit:1;
unsigned m_2ndBit:2;
unsigned m_3rdBit:3;
};
int main(int argc, char* argv[])
{
Bits myBits;
myBits.m_1stBit = 1;
myBits.m_2ndBit = 0;
myBits.m_3rdBit = 1;
printf("size of the myBits is: %d\n", sizeof(myBits));
printf("myBits.m_1stBit = %d\n", myBits.m_1stBit);
printf("myBits.m_2ndBit = %d\n", myBits.m_2ndBit);
printf("myBits.m_3rdBit = %d\n", myBits.m_3rdBit);
return 0;
}
|
|
|
|
|
Serge Krynine wrote:
struct Bits
{
unsigned m_1stBit:1;
unsigned m_2ndBit:2;
unsigned m_3rdBit:3;
};
That is incorrect, the number after the colon is how many bits to use for that variable, so that struct uses 6 bits total, not 3. The correct code is:
struct Bits
{
unsigned m_1stBit:1;
unsigned m_2ndBit:1;
unsigned m_3rdBit:1;
};
--Mike--
Latest blog entry: *drool* (Alyson) [May 10]
Ericahist | Homepage | RightClick-Encrypt | 1ClickPicGrabber
"You have Erica on the brain" - Jon Sagara to me
|
|
|
|
|
|
Actually, you should declare your struct with padding out to the width of the datatype that you declare as the bits. EX:
struct Bitflags
{
unsigned char Bit1 : 1;
unsigned char Bit1 : 1;
unsigned char Bit1 : 1;
unsigned char Padding : 5;
};
|
|
|
|
|
I need to 'tag' a binary file I generate with a key value. I can't change the file format since a third-party vendor is using the output. I remember a Win32 class I took long ago where there was a way to write info to an NTFS file separate from it's data, almost like a file namespace. Anyone know how to do this?
I found more info:
Using the optional "named" attributes.
From a console window do this: echo some_guid_key_string > test.txt:key
How to read/write the named key data attribute from a fstream or hFile?
|
|
|
|
|
You found the answer, they're called streams. You can use a ":streamname" construct with any API that takes a file name. So you could open the file called "yourdatafile:mystream" and then any reads/writes you do are directed to that stream.
--Mike--
Latest blog entry: *drool* (Alyson) [May 10]
Ericahist | Homepage | RightClick-Encrypt | 1ClickPicGrabber
"You have Erica on the brain" - Jon Sagara to me
|
|
|
|
|
Ok, I'm making a file converter for a legacy app and it formats it's numbers lamely.
i.e.:
Normal c++ format:
1.5625E-002
Lame legacy app:
0.15625E-01
So I have 2 options: 1. Find the right format options, or 2. Split the number (represented in a std::string) @ the E and divide the ffirst half by 10, and add 1 to the exponent.
Now my question is:
A. Is there an easy way to format the number? (Lame Legacy format)
B. How do I easily split a std::string without going through all kinds of tepm assignments and sorry hoops?
- Nitron
"Those that say a task is impossible shouldn't interrupt the ones who are doing it." - Chinese Proverb
|
|
|
|
|
I think the following can do the trick:
#include <iostream>
#include <string>
#include <stdio.h>
std::string legacy_display(double x)
{
char buff[256];
sprintf(buff,"%.4lE",x);
int integer_part;
int fractional_part;
int exponent;
sscanf(buff,"%d.%dE%d",&integer_part,&fractional_part,&exponent);
if(integer_part>=0){
sprintf(buff,"0.%d%.4dE%+.2d",integer_part,fractional_part,exponent+1);
}else{
sprintf(buff,"-0.%d%.4dE%+.2d",-integer_part,fractional_part,exponent+1);
}
return buff;
}
int main()
{
std::cout<<legacy_display(1.5625E-002)<<std::endl;
std::cout<<legacy_display(1.5625E+005)<<std::endl;
std::cout<<legacy_display(0.0)<<std::endl;
std::cout<<legacy_display(1.0)<<std::endl;
std::cout<<legacy_display(-1.0)<<std::endl;
return 0;
}
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
|
|
|
|
|
Thanks Joaquín !
- Nitron
"Those that say a task is impossible shouldn't interrupt the ones who are doing it." - Chinese Proverb
|
|
|
|
|
Both the following are valid C++ and have the same meaning:
const int i = 0;
int const j = 0;
The first style is widely used, and everyone will recognise and understand it. The second style is not so immediately understandable to most developers. However, always putting the const qualifier immediately to the right of what it qualifies can prevent some esoteric bugs. There's a brief discussion of why, with examples, here[^], in the section titled Avoiding confusion by using a good programming style. I only found a few other examples when I searched a few weeks ago, so it's safe to assume the second method is not widely known.
In your opinion, is the safer, but less well-known and understood style "better" than the widely-used one, or not?
For what it's worth, I think the safer style is "better", but obviously changing such a deeply engrained style across a development team or organisation is likely to prove difficult.
Gavin Greig
"Haw, you're no deid," girned Charon. "Get aff ma boat or ah'll report ye."
Matthew Fitt - The Hoose O Haivers: The Twelve Trauchles O Heracles.
|
|
|
|
|
"const int" and "int const" are absolutely identical in meaning. I've literally never seen "int const" outside of reference books and web pages.
The "avoiding confusion" section in the quoted page is actually about programming style, which is a highly personal issue.
--Mike--
Latest blog entry: *drool* (Alyson) [May 10]
Ericahist | Homepage | RightClick-Encrypt | 1ClickPicGrabber
"You have Erica on the brain" - Jon Sagara to me
|
|
|
|
|
Maybe my examples weren't best chosen. As the article I referred to points out, the position of the const qualifier can become significant when you introduce a pointer or reference. So although "const int" and "int const" are identical, "const int*" and "int* const" are not. The first is a pointer to a const int, while the second is a const pointer to a non-const int.
Of course, you might not make this error if you separate the pointer from the type, because "const int *" and "int const *" are also identical in meaning.
Thinking in terms of always putting const to the right of what you are making const would help to avoid this sort of confusion.
Now, if you are using typedefs, it can be more confusing still:
typedef int * PINT;
typedef const PINT CPINT;
typedef const int * PCINT;
It might be "reasonable" to expect, when attempting to understand line 2 that the type defined in line 3 would be identical, because all we've done is substitute "int *" for the typedef PINT - but the result is not the same. However, if you adopt the "const to the right" convention, then making that direct substitution does work:
typedef int * PINT;
typedef PINT const CPINT;
typedef int * const CPINT;
Of course, you could say that you'll never write such a typedef, but the typedef could be created by someone else within a template - Loki makes use of typedefs in its Typelists, for example - and if you're not using the "const to the right" convention then it will be harder to understand and debug any resulting issues.
So yes, it is a style issue, but there is at least one specific circumstance in which it will commonly lead to an incorrect understanding of the way C++ works, and poor understanding leads directly to bugs.
What I was really hoping for were some opinions as to whether an improvement in long term understandability of code justified the short term confusion that would be inevitable by overturning a long-standing convention?
Reference: "C++ Templates - The Complete Guide", David Vandevoorde and Niccolai Josuttis.
There is also a short article (c.1998), available somewhere online, which seems to have been the first to raise this issue, but unfortunately I haven't managed to find it again to provide a link.
Gavin Greig
"Haw, you're no deid," girned Charon. "Get aff ma boat or ah'll report ye."
Matthew Fitt - The Hoose O Haivers: The Twelve Trauchles O Heracles.
|
|
|
|
|
I am trying to convert a service skeleton to unicode and I have run into a problem with the event logging. The function void CService::LogEvent(LPCSTR pFormat, ...) and has problems with parsing arguments. This is the original code that compiles under MBCS:
void CService::LogEvent(LPCSTR pFormat, ...)
{
TCHAR chMsg[256];
...
va_list pArg;
va_start(pArg, pFormat);
vsprintf(chMsg, pFormat, pArg);
va_end(pArg);
...
printf(chMsg);
}
so the following code will output Text=1
DWORD dw=1;
LogEvent("Text=%d", dw);
My code:
void CService::LogEvent(LPCSTR pFormat, ...)
{
TCHAR chMsg[256];
...
va_list pArg;
va_start(pArg, pFormat);
vswprintf(chMsg, (LPCTSTR)pFormat, pArg);
va_end(pArg);
...
printf("%s", chMsg);
}
will output Text=%d
I can't just print straight out each time because the LogEvent uses the chMsg string differently when its running as a services vs. a console app. Does anyone have an suggestions?
Matt
BURN HIM! - David Wulff
|
|
|
|
|
Ummm, having trouble finding a well defined question.
However that aside, if you are using TCHAR then you should also use a #define'd version of vsprintf i.e. _vstprintf().
Also, you might actually want to use _vsntprintf() instead to help prevent buffer overrun.
I'm not sure what you were asking with regard to the printf() statement.
...cmk
|
|
|
|
|
cmk wrote:
Ummm, having trouble finding a well defined question.
Oh, sorry. My problem was that instead of formating the DWORD value into the string, it was just printing the %d and ignoring the value.
Matt
BURN HIM! - David Wulff
|
|
|
|
|
Matt Newman wrote:
cmk wrote:
Ummm, having trouble finding a well defined question.
Oh, sorry. My problem was that instead of formating the DWORD value into the string, it was just printing the %d and ignoring the value.
Matt
Oh yes, i see what you were asking now.
The problem is likely that you are passing in straight char* "Text=%d" and yet using the unicode version which will expect ALL string parameters to be unicode.
Using the TCHAR is an all or nothing proposition.
Wrap all literal strings with _T() e.g. _T("Text=%d").
Personally i gave up on using all that as there were cases when i needed both ansi and unicode strings.
...cmk
|
|
|
|
|