|
Did you have something like this :-
class MainFrame
{
private:
PaintTool* m_pTool;
}
class PaintTool
{
...
};
class PaintTool1 : PaintTool
{
};
class PaintTool2 : PaintTool
{
};
Where does multiple inheritance figure in this?
|
|
|
|
|
I don't see how you were asking about multiple inheritance, I thought you wanted to know about virtual base classes ? Did you mean to emphasise the plural, i.e. more than one virtual base ?
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
|
|
|
|
|
My understanding of virtual base classes.
(Excuse the C# style synatx)
class A
{
int x;
}
class B : A
{
}
class C : A
{
}
class D : B, C
{
}
In case of D there will be two distinct copied of data for A as it is not virtual base.
D* pd = new D;
C* pc = (C*)pd;
pc->x = 10;
B* pb = (B*)pd;
//pc->x is not same as pb->x
pb->x = 11;
Now decalring like this
class B : virtual A
{
}
class C : virtual A
{
}
class D : B, C
{
}
In this case,
C* pc = (C*)pd;
pc->x = 10;
B* pb = (B*)pd;
//pc->x is same as pb->x
ASSERT(pc->x == pb->x)
This is what I always understood the purpose of virtual base classes. Am I wrong?
|
|
|
|
|
A virtual base class has at least one pure virtual function
virtual void PaintNow(CDC & DC) =0;
Therefore it cannot be instantiated, it exists somewhat like an interface as I understand it in C# ( which is to say barely ). Multiple inheritance is possible, but in no way implied by the fact that a class is a virtual base. It simply means the class itself cannot be instantiated, because it defines functions that derived classes MUST impliment ( which is it's function ).
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:
A virtual base class has at least one pure virtual function
I thought that was abstract class.
Don't know what is the emoticon for that feeling.
|
|
|
|
|
You are right, that is an abstract base class.
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!
|
|
|
|
|
That will create an abstract base class.
A virtual base class is used in multiple inheritance where you derive from two classes that derive from a common class like so:
class a;
class b : public a;
class c : public a;
class d: public b, public c;
Obviously this isn't valid C++ but hopefully you get the idea. In this case, you will get two intstances of the class a in class d. One that is a part of class b, the other that is a part of class c.
If you create a virtual base class with a, this will make it so that only one instance of a appears in the final class d, and this will prevent collisions because of the duplicate variables.
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!
|
|
|
|
|
The only real-world example I know of useful virtual base classes is std::iostream which derives from ostream and istream . Each of those derive from (I think) ios virtually, so iostream ends up with only instance of ios in its inheritance tree.
--Mike--
Just released - RightClick-Encrypt - Adds fast & easy file encryption to Explorer
Like the Google toolbar? Then check out UltraBar, with more features & customizable search engines!
My really out-of-date homepage
Sonork - 100.10414 AcidHelm
|
|
|
|
|
You are right, I totally forgot about it. Thanks
|
|
|
|
|
Hi,
I tried to merge two projects together. The second (some OpenGL things) doesn't use precompiled headers at all, in those files I get errors when compiling.
Is the a precompiler pragma to disable use of precompiled headers for a file?
|
|
|
|
|
#pragma no_pch
does NOT work to suppress precompiled header, hmm any idea?
|
|
|
|
|
I case you're satisfied with a solution not involving pragmas, you can go to Project->Settings and tune the precompiled headers feature for each file separately (just click on the file alone instead of the whole project and search thru the tabs for it.)
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
|
|
|
|
|
a solution with pragma would be very convenient
if someone has a solution or a workaround, let me know. thx
|
|
|
|
|
|
Rama Krishna wrote:
look at #pragma hdrstop
and then?
#pragma hdrstop alone doesn't help, still the same compiler error
|
|
|
|
|
In project settings, c++ tab, precompiled headers in the dropdown. Then select the files you don't want precompiled headers from the tree on the right, and pick "Not using precompiled headers".
Joel Lucsy (jjlucsy@ameritech.net)
|
|
|
|
|
Hi:
I am stuck at converting a CString to a float number and actually determining if the string is a number. In other words I want to be able to tell that
"23" is 23
"23.554" is 23.554
"gdfgd" is invalid
"34.4353n" is invalid
"45.45.34" is invalid
etc.
Any thoughts????
Thank you
|
|
|
|
|
I don't know about case 4, but here's a quick and dirty check:
bool convertToFloat
(CString& strNumber,
float& fValue)
{
float floatValue = 0.0;
if (sscanf (strNumber, "%f", &floatValue) == 1) {
fValue = floatValue;
return (true);
}
return (false);
} /ravi
Let's try putting "civil" back into "civilization"
http://www.ravib.com
ravib@ravib.com
|
|
|
|
|
I have posted an article with some helper functions.
http://www.codeproject.com/cpp/helper_functions_01.asp
One of these is an IsDecimal. You can strip the IsDecimal function and use it sperately from the rest if you want. You should be able to combine IsDecimal and a call to atof to achieve what you want.
|
|
|
|
|
You could loop through all the chars in the string and use the isdigit() function on each char...
There might be faster ways, just an idea...
- Anders
Money talks, but all mine ever says is "Goodbye!"
|
|
|
|
|
_tcstod(...) and its non-unicode equivalent let u pass the number string to convert and a pointer to the char that ended the conversion ... when it returns examine the pointer to the char that ended the conversion and see if its a '\0' ... if it is then the string was all numeric else it wasn't
"... and so i said to him ... if it don't dance (or code) and you can't eat it either f**k it or throw it away" sonork: 100.18128 8028finder.com
|
|
|
|
|
Could you use the atof function.
If it returns 0.0 then it can't be converted to a nummer, otherwise it will return the number.
-Raffi
|
|
|
|
|
Okay, what about if the value is "0.0"?
"One good thing about getting older, you don't lose the ages you've been!"
|
|
|
|
|
|
Hi, if somebody could just give a look at this code :
Iknow it's not C++, it's only C....
I don't know what I do wrong....
Thanks a lot
Starn
[code]
/* This little piece of code initiate 2 queue
**First queue is filled of empty buffers
**second queue is filled with the full buffers
**PROBLEM : I can only fill the 2 first buffers in the FOR loop
** queueX.h contains the TAILQ macros. (see after the main function...)
*/
//I know, I don't need all these includes... (it's for other functions...)
#include <stdio.h>
#include <unistd.h>
#include <atomic.h>
#include <malloc.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <net/if_types.h>
#include <netinet/in.h>
#include <sys/syspage.h>
#include <sys/neutrino.h>
#include <syslog.h>
#include <sys/dispatch.h>
#include <sys/io-net.h>
#include <string.h>
#include <stdbool.h>
#include<sys/queueX.h>
#define NB_BY 192 // 192 bytes = 1536 bits = 2x 48 échantillons de 16 bits car 1 ms = 2 x 48 ech à 48000Hz
int msg_thread_send;
TAILQ_HEAD(buffers,entry) head;
struct buffers *headp;
struct entry{
char data[NB_BY];
TAILQ_ENTRY(entry) entries;
} *n1, *n2, *n3,*n4,*n5, *np,*sendp,*ready_sendp;
TAILQ_HEAD(send,entry) head_send;
struct send *head_sendp;
int main()
{
FILE *file1;
int i, file_size;
if ((file1 = fopen ("/home/s_16_44.wav", "r")) == 0)
printf ("can not open file\n ");
fseek(file1, 0, SEEK_END);
file_size=ftell(file1);
fseek(file1, 48, SEEK_SET);
TAILQ_INIT (&head);
TAILQ_INIT (&head_send);
n1 = malloc(sizeof(struct entry)); /* Insert at the head. */
TAILQ_INSERT_HEAD(&head, n1, entries);
n2 = malloc(sizeof(struct entry)); /* Insert at the tail. */
TAILQ_INSERT_AFTER(&head, n1,n2, entries);
//TAILQ_INSERT_TAIL(&head, n1, entries);
n3 = malloc(sizeof(struct entry)); /* Insert at the tail. */
TAILQ_INSERT_AFTER(&head, n2,n3, entries);
//TAILQ_INSERT_TAIL(&head, n4, entries);
n4 = malloc(sizeof(struct entry)); /* Insert at the tail. */
TAILQ_INSERT_AFTER(&head,n3, n4, entries);
//TAILQ_INSERT_TAIL(&head, n4, entries);
n5 = malloc(sizeof(struct entry)); /* Insert at the tail. */
TAILQ_INSERT_TAIL(&head, n5, entries);
for (np = head.tqh_first; np != NULL; np = np->entries.tqe_next)
{
fread(np->data,NB_BY,1,file1);
if(np=head.tqh_first)
{
TAILQ_INSERT_HEAD(&head_send, np, entries);
printf("insert_head\n");
}
else
TAILQ_INSERT_TAIL(&head_send, np, entries);
printf("insert_queue\n");
}
np=head.tqh_first;
//ready_sendp=head_send.tqh_first;
// ICI, démarrer le thread_send
while(1)
{
if(msg_thread_send) //tant que le thread_send n'a pas mis ce bit à , il n'y a pas de buffer de libre
{
fread(np->data,NB_BY,1,file1);
// if(j>4)
//{
TAILQ_INSERT_TAIL(&head_send, np, entries);
//voir si il ne faut pas retirer le premier élément de la queue_send (memory leacks) ca devrait être arrangé avec TAILQ_REMOVE
np = np->entries.tqe_next;
msg_thread_send=0;
}
if( np == NULL) //si on est au bout de la queue, on revient au début...
np=head.tqh_first;
}
// printf("data : %c\n",n1->data);
fclose(file1);
return(0);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
* Tail queue declarations.
*/
#define TAILQ_HEAD(name, type) \
struct name { \
struct type *tqh_first; /* first element */ \
struct type **tqh_last; /* addr of last next element */ \
}
#define TAILQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).tqh_first }
#define TAILQ_ENTRY(type) \
struct { \
struct type *tqe_next; /* next element */ \
struct type **tqe_prev; /* address of previous next element */ \
}
/*
* Tail queue functions.
*/
#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
#define TAILQ_FIRST(head) ((head)->tqh_first)
#define TAILQ_FOREACH(var, head, field) \
for ((var) = TAILQ_FIRST((head)); \
(var); \
(var) = TAILQ_NEXT((var), field))
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
for ((var) = TAILQ_LAST((head), headname); \
(var); \
(var) = TAILQ_PREV((var), headname, field))
#define TAILQ_INIT(head) do { \
TAILQ_FIRST((head)) = NULL; \
(head)->tqh_last = &TAILQ_FIRST((head)); \
} while (0)
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
TAILQ_NEXT((elm), field)->field.tqe_prev = \
&TAILQ_NEXT((elm), field); \
else \
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
TAILQ_NEXT((listelm), field) = (elm); \
(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
} while (0)
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
TAILQ_NEXT((elm), field) = (listelm); \
*(listelm)->field.tqe_prev = (elm); \
(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
} while (0)
#define TAILQ_INSERT_HEAD(head, elm, field) do { \
if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
TAILQ_FIRST((head))->field.tqe_prev = \
&TAILQ_NEXT((elm), field); \
else \
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
TAILQ_FIRST((head)) = (elm); \
(elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
} while (0)
#define TAILQ_INSERT_TAIL(head, elm, field) do { \
TAILQ_NEXT((elm), field) = NULL; \
(elm)->field.tqe_prev = (head)->tqh_last; \
*(head)->tqh_last = (elm); \
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
} while (0)
#define TAILQ_LAST(head, headname) \
(*(((struct headname *)((head)->tqh_last))->tqh_last))
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
#define TAILQ_PREV(elm, headname, field) \
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
#define TAILQ_REMOVE(head, elm, field) do { \
if ((TAILQ_NEXT((elm), field)) != NULL) \
TAILQ_NEXT((elm), field)->field.tqe_prev = \
(elm)->field.tqe_prev; \
else \
(head)->tqh_last = (elm)->field.tqe_prev; \
*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
} while (0)
[/code]
|
|
|
|
|