LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 12-08-2009, 05:52 PM   #31
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled

Quote:
Originally Posted by MTK358 View Post
http://yosefk.com/c++fqa/defective.html

What's better about C:

See "Duplicate Facilities"

What's better about Java:

See "No high-level built-in types"
See "Manual memory management"
Most of what I do in C++ can't be done in Java because Java pretends like objects are these nebulous things that have no underlying structure. Because of that, one can't use pointers, not to mention nested pointers, which are critical to a lot of C++ (pointers aren't actually outdated; you don't see JVM written in Java.) This prevents a significant portion of the useful C/C++ code out there from working in Java without significant restructuring, namely by creation of wrapper classes to simulate references. Additionally, Java's "memory management" means "I'll clean it up when I feel like it," much like a custodial contractor who says emptying your own trash is a contract violation. Java and C++ cannot be fairly compared, despite their syntactic and semantic similarities. Java isn't "the new C++" just as C++ isn't "the original Java."
Kevin Barry
 
Old 12-08-2009, 08:06 PM   #32
MTK358
LQ 5k Club
 
Registered: Sep 2009
Posts: 6,443
Blog Entries: 3

Original Poster
Rep: Reputation: 713Reputation: 713Reputation: 713Reputation: 713Reputation: 713Reputation: 713Reputation: 713
Quote:
Originally Posted by tuxdev View Post
When you switch the second and third parameters, it tends not to be able to find the function.

The Makefile is much more complex than it needs to be - use make's implicit rules and GCC's dependency checking:
Code:
CXXFLAGS = -Wall -Wextra -Weffc++ -Werror `pkg-config x11 --cflags` `pkg-config cairo --cflags` -MD
LDFLAGS = `pkg-config x11 --libs` `pkg-config cairo --libs`
LINK.o = $(LINK.cpp)
.PHONY = all clean
SRCS = $(wildcard src/*.cpp)

all: main

main: $(SRCS:%.cpp=%.o)

clean:
    $(RM) -f main *.o *.d

-include *.d
OK, I'll try continuing in C++, maybe I just need to learn more. Anyway, how do get this to compile?
 
Old 12-09-2009, 02:05 AM   #33
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 453Reputation: 453Reputation: 453Reputation: 453Reputation: 453
Quote:
Originally Posted by ta0kira View Post
Most of what I do in C++ can't be done in Java because Java pretends like objects are these nebulous things that have no underlying structure. Because of that, one can't use pointers, not to mention nested pointers, which are critical to a lot of C++ (pointers aren't actually outdated; you don't see JVM written in Java.) This prevents a significant portion of the useful C/C++ code out there from working in Java without significant restructuring, namely by creation of wrapper classes to simulate references. Additionally, Java's "memory management" means "I'll clean it up when I feel like it," much like a custodial contractor who says emptying your own trash is a contract violation. Java and C++ cannot be fairly compared, despite their syntactic and semantic similarities. Java isn't "the new C++" just as C++ isn't "the original Java."
Kevin Barry
You don't even see JVM written in C++ - it's written in "C".
 
Old 12-09-2009, 06:33 AM   #34
johnsfine
Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,051

Rep: Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100
Quote:
Originally Posted by MTK358 View Post
Anyway, how do get this to compile?
Look at the error messages you quoted:
Code:
src/main.cpp:7: error: no matching function for call to ‘TopLevelWindow::TopLevelWindow(Application*, const char [10], Dimension)’
src/TopLevelWindow.h:16: note: candidates are: TopLevelWindow::TopLevelWindow(Application*, Dimension, std::string)
That says you called a function using parameter types:
Application*, const char [10], Dimension
but you defined the function using parameter types
Application*, Dimension, std::string

The C++ compiler generally can do an implicit conversion from const char[10] to std::string. But it can't switch the operand sequence. You defined the function with the Dimension third and std::string second, but called it with those reversed.

After you fix that bug, maybe the code will compile. If not, you should post the relevant code. The makefile plus the error messages is usually not enough for us to guess what error you made.

Last edited by johnsfine; 12-09-2009 at 06:35 AM.
 
Old 12-09-2009, 07:30 AM   #35
MTK358
LQ 5k Club
 
Registered: Sep 2009
Posts: 6,443
Blog Entries: 3

Original Poster
Rep: Reputation: 713Reputation: 713Reputation: 713Reputation: 713Reputation: 713Reputation: 713Reputation: 713
Code:
$ make
g++ -c -lX11 -I /usr/include/cairo -lcairo -Werror src/main.cpp
src/Widget.h: In function ‘int main()’:
src/Widget.h:27: error: ‘void Widget::show()’ is inaccessible
src/main.cpp:8: error: within this context
src/main.cpp:8: error: ‘Widget’ is not an accessible base of ‘TopLevelWindow’
make: *** [main.o] Error 1
Code:
#ifndef TopLevelWindow_H
#define TopLevelWindow_H

#include <X11/Xlib.h>
#include <string>
#include <cstdlib>

#include "Application.h"
#include "Widget.h"
#include "Dimension.h"

class TopLevelWindow : Widget {
	private:
		//Nothing!
	public:
		TopLevelWindow(Application* app, Dimension size, std::string newTitle);//, Dimension newPadding);
};

#endif
Code:
#ifndef Widget_H
#define Widget_H

#include <X11/Xlib.h>
#include <cairo.h>
#include <cairo-xlib.h>

#include "Dimension.h"

class Widget {
	private:
		Display* display;
		int screen;
		Widget* parent;
		Window window;
		bool focusable;
		cairo_surface_t* cairoSurface;
	public:
		Widget();
		Widget(Widget* parent_, Dimension location, Dimension size);

		void setFocusable(bool focusable_);
		bool getFocusable();

		Dimension getSize();
		Dimension getLocation();

		void show();
		void hide();
		bool isVisible();

		void setWindow(Window window_);
		void setDisplay(Display* display_);
		void setScreen(int screen_);

		Window getWindow();
		Display* getDisplay();
		int getScreen();

		void paint();
};

#endif
Still, wouldn't it be nice if you could write C as if structs had inheritance, and run it through a special program that turns it into C?

Last edited by MTK358; 12-09-2009 at 07:31 AM.
 
Old 12-09-2009, 07:35 AM   #36
MTK358
LQ 5k Club
 
Registered: Sep 2009
Posts: 6,443
Blog Entries: 3

Original Poster
Rep: Reputation: 713Reputation: 713Reputation: 713Reputation: 713Reputation: 713Reputation: 713Reputation: 713
OK, I found that

Code:
TopLevelWindow : Widget
should be

Code:
TopLevelWindow : public Widget
But doesn't this concept break the OO rule of private, protected, and public? Why do you have to decide suddenly?
 
Old 12-09-2009, 07:39 AM   #37
MTK358
LQ 5k Club
 
Registered: Sep 2009
Posts: 6,443
Blog Entries: 3

Original Poster
Rep: Reputation: 713Reputation: 713Reputation: 713Reputation: 713Reputation: 713Reputation: 713Reputation: 713
I got a segfault and ran GDB on the program, and found that the way they say C++ debugging info is not human readable is true:

Code:
#0  0x000000000040134a in TopLevelWindow::TopLevelWindow (this=0x7fffffffe110, app=0x7fffffffe030, size=..., newTitle=Traceback (most recent call last):
  File "/usr/lib64/../share/gdb/python/libstdcxx/v6/printers.py", line 469, in to_string
    return self.val['_M_dataplus']['_M_p'].string (encoding, length = len)
RuntimeError: Error reading string from inferior: Input/output error
) at src/TopLevelWindow.cpp:6
#1  0x0000000000400db6 in main () at src/main.cpp:7
 
Old 12-09-2009, 07:55 AM   #38
johnsfine
Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,051

Rep: Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100
Once again, you have quoted multiple error messages (compile time and run time) from the first few lines of main() in your code. You posted lots of code and never the lines containing the errors.

Quote:
Originally Posted by MTK358 View Post
Still, wouldn't it be nice if you could write C as if structs had inheritance, and run it through a special program that turns it into C?
Doesn't sound like a good idea. You think you would do a better job of extending C into OO than the designers of C++ did. Even with a better job (which is unlikely and difficult) merely a little better doesn't balance the fact that C++ is already in widespread use.

Quote:
Originally Posted by MTK358 View Post
But doesn't this concept break the OO rule of private, protected, and public? Why do you have to decide suddenly?
Why does it break any OO concept.

You accessed the Widget part of TopLevelWindow from outside TopLevelWindow. If you want to do that, Widget must be public in TopLevelWindow.

If you don't want Widget to be public in TopLevelWindow, then TopLevelWindow must provide some interface to do whatever it was that you wanted to do on line 8 of main.cpp (which you didn't show us).

Possibly a using declaration gives you a way to achieve what you want (expose only part of Widget to users of TopLevelWindow). I'm not 100% sure myself what you can/cannot do with using. I don't often want to expose only part of a base class. I use using a lot to cover a trickier flaw in the C++ language involving inheritance from templated base classes.

Quote:
Originally Posted by MTK358 View Post
found that the way they say C++ debugging info is not human readable is true:
Yes. It is unreadable. But not so unreadable that you can't easily tell something is going wrong in the constructor of TopLevelWindow. Of course you showed us only the declaration, not the definition (nor the call to it from main), consistent with your apparent policy of never showing any of the lines where the errors occur.

Last edited by johnsfine; 12-09-2009 at 08:03 AM.
 
Old 12-09-2009, 08:08 AM   #39
MTK358
LQ 5k Club
 
Registered: Sep 2009
Posts: 6,443
Blog Entries: 3

Original Poster
Rep: Reputation: 713Reputation: 713Reputation: 713Reputation: 713Reputation: 713Reputation: 713Reputation: 713
I misunderstood the way BaseClass : public DerivedClass works. And I still don't understand why you would ever want to block access to the part of your class inherited from base.

Code:
TopLevelWindow.cpp:6:

setWindow(XCreateSimpleWindow(getDisplay(), RootWindow(getDisplay(), getScreen()), 0, 0, 100, 100, 0, BlackPixel(getDisplay(), getScreen()), WhitePixel(getDisplay(), getScreen())));

main.cpp:7:

TopLevelWindow win(&app, Dimension(3, 3), "Test");
Code:
(gdb) bt
#0  0x000000000040134a in TopLevelWindow::TopLevelWindow (this=0x7fffffffe110, app=0x7fffffffe030, size=..., newTitle=Traceback (most recent call last):
  File "/usr/lib64/../share/gdb/python/libstdcxx/v6/printers.py", line 469, in to_string
    return self.val['_M_dataplus']['_M_p'].string (encoding, length = len)
RuntimeError: Error reading string from inferior: Input/output error
) at src/TopLevelWindow.cpp:6
#1  0x0000000000400db6 in main () at src/main.cpp:7
That debug message still doesn't even give me a clue to what's wrong. In C debug messages are usually quite obvious, however.

Last edited by MTK358; 12-09-2009 at 08:10 AM.
 
Old 12-09-2009, 08:26 AM   #40
johnsfine
Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,051

Rep: Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100
Quote:
Originally Posted by MTK358 View Post
I misunderstood the way BaseClass : public DerivedClass works.
But you understand now?

Quote:
I still don't understand why you would ever want to block access to the part of your class inherited from base.
If you always want your base classes public, always make your base classes public.

I usually make base classes public (whether they ought to be or not) because I don't really believe in the supposed benefits of maximum encapsulation. But I still have found reasons (in complex projects) to make base classes private, so I'm glad I have the option to do so.

Code:
setWindow(XCreateSimpleWindow(getDisplay(), RootWindow(getDisplay(), getScreen()), 0, 0, 100, 100, 0, BlackPixel(getDisplay(), getScreen()), WhitePixel(getDisplay(), getScreen())));
I think we needed to see the whole definition of that constructor, especially the way it invokes the base class constructor. If you let it use the default constructor for the base class, I don't think that is a valid way to inherit your Widget class (and wouldn't be in any OO langauge).

Quote:
That debug message still doesn't even give me a clue to what's wrong. In C debug messages are usually quite obvious, however.
I use too many different debuggers, so I didn't initially see what was what in the gdb output you quoted. Even in C, when your program trashes its own context that badly before the seg fault, the debugger will often display nonsense.

Your code constructed a temporary std::string containing "test" and then called the TopLevelWindow constructor. Inside that constructor, the code trashed the memory occupied by that temporary std::string before the string went out of scope.

You may need to single step into the constructor and into or over each of the things the constructor does, in order to discover the moment at which some probably unrelated write steps on the memory used by that temporary std::string.

I programmed in assembly language for many years before I ever tried C++, so I use an assembly language view for debugging any C++ bug as tricky as the one you seem to have. If you know assembly language, these bugs are usually far easier to diagnose in an assembler view.

Last edited by johnsfine; 12-09-2009 at 08:31 AM.
 
Old 12-09-2009, 08:43 AM   #41
MTK358
LQ 5k Club
 
Registered: Sep 2009
Posts: 6,443
Blog Entries: 3

Original Poster
Rep: Reputation: 713Reputation: 713Reputation: 713Reputation: 713Reputation: 713Reputation: 713Reputation: 713
Here's the TopLevelWindow constructor (ignore the fact that the size parameter isn't used, all I want for now is for it to just display a window):

Code:
TopLevelWindow::TopLevelWindow(Application* app, Dimension size, std::string newTitle) {//, Dimension newPadding, Widget* child) {
	setDisplay(app->getDisplay());
	setScreen(app->getScreen());
	setWindow(XCreateSimpleWindow(getDisplay(), RootWindow(getDisplay(), getScreen()), 0, 0, 100, 100, 0, BlackPixel(getDisplay(), getScreen()), WhitePixel(getDisplay(), getScreen())));
	XStoreName(getDisplay(), getWindow(), newTitle.c_str());
}
EDIT: I found the problem, the part that I left out is highlited in red. Now it actually shows a window on the screen.

And I don't know Assembler. The only working assembly program I have written was for an 8-bit AVR microcontroller to blink a few LEDs.

But I hope to learn eventually. It still puzzles me the way I keep hearing that the memory addreses are preset in the executable, what if there is not enough memory? Or that address is used? How does it call parts of other programs?
 
Old 12-09-2009, 09:10 AM   #42
johnsfine
Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,051

Rep: Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100
Quote:
Originally Posted by MTK358 View Post
EDIT: I found the problem, the part that I left out is highlited in red. Now it actually shows a window on the screen.
I think I see how you managed to get away with letting the compiler generate a default construction of the base class rather than explicitly calling the base class constructor yourself. But that is an error prone style, and I strongly suggest you get in the habit of explicitly calling base class constructors whenever the base class requires interesting initialization.

In these situations, I usually do a typedef for super and then use super, rather than the actual base class name everywhere else within the current class. That style has significant benefits as your projects get more complex, even more so when inheriting from templated classes.

In C++, a class may have more than one base class. So the language could not have been designed (like Java) to define super for you. Even with multiple base classes, I usually find that only one of my base classes is conceptually "super". Then that typedef also serves to tell maintainers of the code which base class I considered "super" in designing this class.

So
Code:
class TopLevelWindow : public Widget {
        typedef Widget super;
	private:
		//Nothing!
	public:
		TopLevelWindow(Application* app, Dimension size, std::string newTitle);
};
Then
Code:
TopLevelWindow::TopLevelWindow(Application* app, Dimension size, std::string newTitle) : //, Dimension newPadding, Widget* child)
        super( ??, ??, size )
{
	setDisplay(app->getDisplay());
	setScreen(app->getScreen());
	setWindow(XCreateSimpleWindow(getDisplay(), RootWindow(getDisplay(), getScreen()), 0, 0, 100, 100, 0, BlackPixel(getDisplay(), getScreen()), WhitePixel(getDisplay(), getScreen())));
	XStoreName(getDisplay(), getWindow(), newTitle.c_str());
}
I don't understand your code well enough to know what you want for Widget* parent_, Dimension location in that call to super(), but I suspect you ought to be making those explicit (rather than using the default constructor).

I also prefer to use struct rather than class, because I don't like excessive encapsulation, I like to put the public interface first, I like public to be the default and initial state and private or protected to need to be explicit.

Last edited by johnsfine; 12-09-2009 at 09:17 AM.
 
1 members found this post helpful.
Old 12-09-2009, 09:36 AM   #43
MTK358
LQ 5k Club
 
Registered: Sep 2009
Posts: 6,443
Blog Entries: 3

Original Poster
Rep: Reputation: 713Reputation: 713Reputation: 713Reputation: 713Reputation: 713Reputation: 713Reputation: 713
The problem is that the TopLevelWindow obviously does not have a parent Widget.

One solution may be to add a parameter-less constructor for Widget.

So I can write "typedef <base class> super;" and that will call the base class constructor? Will calling "super.method()" call the base class's implementation of the method?

And I still think I would like to use class instead of struct because my classes often have a few private fields and I think it's convenient to have them there at the top. I prefer to use structs the way they are used in plain C.
 
Old 12-09-2009, 09:56 AM   #44
johnsfine
Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,051

Rep: Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100
Quote:
Originally Posted by MTK358 View Post
The problem is that the TopLevelWindow obviously does not have a parent Widget.
Is Widget designed to expect self for the top level parent pointer or NULL?

Whichever it is, I think it is more maintainable code to make that explicit in construction of TopLevelWindow, rather than buried in a compiler generated call to the base class default constructor.

If the implementation of parentless is encapsulated inside Widget (as it probably should be) and should not be known by TopLevelWindow, then it should require an explicit parentless constructor of Widget. The special case of a parentless Widget should not be constructed by the default constructor of Widget.

In a lot of my code, I have an empty class named Nothing. In overloads of a function or constructor where not providing a certain parameter is a special enough case to deserve being highlighted at the point of call, I define an overload that takes a Nothing const& as a parameter and explicitly passes Nothing() to satisfy it. (There is no run time overhead to passing Nothing() to a Nothing const&. It just determines which overload is chosen at compile time).

Quote:
One solution may be to add a parameter-less constructor for Widget.
You already declared (and I assume defined) a parameter-less constructor for Widget. I was questioning whether it was a good idea to use that constructor.

Quote:
So I can write "typedef <base class> super;" and that will call the base class constructor?
The typedef just defines the identifier super. By itself, it does not change any generated code. The compiler defaults to calling the parameter-less Widget constructor.

You could call a Widget() constructor yourself in a TopLevelWindow constructor if you wanted to. I just think it is better style to define super and then call the super() constructor instead of the Widget() constructor.

Quote:
Will calling "super.method()" call the base class's implementation of the method?
If you don't define super, then you call base class implementation explicitly with Widget::method(). If you do define super, you can call base class implementation with super::method().

I think the later is usually more maintainable code.

When the base class is templated, you find a lot of need for
typedef typename super::name_of_type name_of_type;
and
using super::name_of_member;
to bring names from the base class into scope for definition time syntax checking of the current class (templated base class names may be in scope when current class methods are instantiated, but aren't when current class methods are defined, so you may need to force them into the definition time scope.)

Last edited by johnsfine; 12-09-2009 at 10:06 AM.
 
Old 12-09-2009, 11:29 AM   #45
MTK358
LQ 5k Club
 
Registered: Sep 2009
Posts: 6,443
Blog Entries: 3

Original Poster
Rep: Reputation: 713Reputation: 713Reputation: 713Reputation: 713Reputation: 713Reputation: 713Reputation: 713
Quote:
Originally Posted by johnsfine View Post
Is Widget designed to expect self for the top level parent pointer or NULL?

Whichever it is, I think it is more maintainable code to make that explicit in construction of TopLevelWindow, rather than buried in a compiler generated call to the base class default constructor.

If the implementation of parentless is encapsulated inside Widget (as it probably should be) and should not be known by TopLevelWindow, then it should require an explicit parentless constructor of Widget. The special case of a parentless Widget should not be constructed by the default constructor of Widget.

In a lot of my code, I have an empty class named Nothing. In overloads of a function or constructor where not providing a certain parameter is a special enough case to deserve being highlighted at the point of call, I define an overload that takes a Nothing const& as a parameter and explicitly passes Nothing() to satisfy it. (There is no run time overhead to passing Nothing() to a Nothing const&. It just determines which overload is chosen at compile time).
The Widget constructor is based around the concept that it is the child of another Widget. A TopLevelWondow's parent is NULL, and TopLevelWindow is a very special case of Widget, mainly because of the fact that it's "parent" is an X Window (usually the root window) instead of another Widget, so it's initialization is quite different and I think it would not be a good idea for Widget itself to handle that case, because it will just make all the other "normal" widgets more complicated. For that reason, I would just make an empty constructor for Widget.

But it still seems kind of confusing for normal widgets.

Maybe it would be best for TopLevelWindow not to be a subclass of Widget but be independent?

Note that the intended class hierarchy was actually Widget->Container->TopLevelWindow, where Container is a widget that holds a single widget with variable padding on all sides (Just about everything but text boxes and labels will be a subclass of Container, borrowing the idea from GTK+ that text labels in widgets are actually child Label widgets). I just did Widget->TopLevelWindow to get results quick.

Last edited by MTK358; 12-09-2009 at 11:31 AM.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
MailScanner alternatives cygnus-x1 Linux - Networking 1 11-28-2006 12:28 AM
trying to find alternatives acey99 Linux - Hardware 1 11-24-2006 10:03 AM
Vi alternatives Gins Linux - General 9 09-05-2005 10:29 AM
Alternatives to x? ampex189 Linux - Software 9 03-22-2005 01:21 PM
Alternatives matahchuah Linux - Software 1 02-17-2004 05:08 PM


All times are GMT -5. The time now is 02:53 PM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration