Solution wide code

Whether you're a newbie or an experienced programmer, any questions, help, or just talk of any language will be welcomed here.

Moderator: Coders of Rage

Post Reply
User avatar
short
ES Beta Backer
ES Beta Backer
Posts: 548
Joined: Thu Apr 30, 2009 2:22 am
Current Project: c++, c
Favorite Gaming Platforms: SNES, PS2, SNES, SNES, PC NES
Programming Language of Choice: c, c++
Location: Oregon, US

Solution wide code

Post by short »

Hmm it looks like my indenting gets messed up when pasted into the code block, oh well.

Code: Select all

 /// Static class methods
#ifdef _WIN32
    static inline const QString VideoFilesDirectory(){
	return QString("../video/");
    }
#else
    static inline const QString VideoFilesDirectory(){
	return QString("/home/user/MyDocs/.videos/");
    }
#endif

    // returns the complete image path for the button name.
    static inline const QString ConstructImagePath(const QString& filename){
	return QString(":/resources/images/" + filename + ".png").toLower();
    }

    // play/pause button text
    static inline const QString PlayPauseButtonTitle(){
	return QString("play_pause");
    }

    // record/stop button text
    static inline const QString RecordStopButtonTitle(){
	return QString("record_stop");
    }

    // play button text
    static inline const QString PlayButtonTitle(){
	return QString("play");
    }

    //pause button text
    static inline const QString PauseButtonTitle(){
	return QString("pause");
    }

    //stop button text
    static inline const QString StopButtonTitle(){
	return QString("stop");
    }

    //record button text
    static inline const QString RecordButtonTitle(){
	return QString("record");
    }

    // menu button text
    static inline const QString MenuButtonTitle(){
	return QString("menu");
    }

    // forward button text
    static inline const QString ForwardButtonTitle(){
	return QString("forward");
    }

    // backwards button text
    static inline const QString BackwardsButtonTitle(){
	return QString("backwards");
    }

    // cut button text
    static inline const QString CutButtonTitle(){
	return QString("cut");
    }

    // undo button text
    static inline const QString UndoButtonTitle(){
	return QString("undo");
    }

    // empty button text
    static inline const QString EmptyButtonTitle(){
	return QString("empty");
    }

    // strip the directory path from the filename
    static inline const QString StripVideoDirectoryPathFromFilename(const QString& filename){
	QString t = filename;
	return t.remove(0, VideoFilesDirectory().length());
    }
    
    /// Public Enumeration
    enum InstanceType {VideoPlayer, VideoEditor, VideoRecorder};

private:
    // no initialization of class allowed
    StaticClass();
    StaticClass(const StaticClass& ref);
Hey guys, so I am writing the last part of my senior design project which is a special video player for the n900 phone. Within my project I have four"projects", a video player, video editor, and video recorder (3 different applications), and a "framework" project. The four projects all share certain variable names with one another, such as the text for the GUI buttons. The functions also share certain functionality needs such as needing the current video file directory.

My solution to this was to create one .h file, the file above, as a purely static class (all the methods are static) where I simply have all the functions I need throughout each application. Elsewhere in my solution, I can just pull the function out of my ass (not quite like pulling a singleton instance out of my ass) ie I can call

Code: Select all

m_InstructionLabel->setText(StaticClass::StripVideoDirectoryPathFromFilename(m_Instance->GetFilename()));
My first question, does anything think this is bad design? 2nd question, originally I tried to initialize static members but got stuck because I never instantiate an instance of the static class. The compiler lets me define a variable as such:

Code: Select all

static QString MenuButtonTitle;
but not

Code: Select all

static QString MenuButtonTitle= "menu";
because if I were to ever create instantiate instances of the static class the linker would shit itself. To get around this, I used the functions I mentioned at the top. Any have a better idea?
My github repository contains the project I am currently working on,
link: https://github.com/bjadamson
User avatar
Falco Girgis
Elysian Shadows Team
Elysian Shadows Team
Posts: 10294
Joined: Thu May 20, 2004 2:04 pm
Current Project: Elysian Shadows
Favorite Gaming Platforms: Dreamcast, SNES, NES
Programming Language of Choice: C/++
Location: Studio Vorbis, AL
Contact:

Re: Solution wide code

Post by Falco Girgis »

Whoah. We both used QT for our senior design projects. :shock:
short wrote:

Code: Select all

static QString MenuButtonTitle= "menu";
That isn't technically an "initialization" with the assignment operator (only basic data types can be initialized with an assignment in C++). You must provide a constructor for the object with that functionality. Luckily, QT does that:

Code: Select all

QString StaticClass::menuButtonTitle("menu");
Buuuuuuuuuuuuuuut... unfortunately you NEVER want to do this. :(

In QT, instantiating any type of QObject before QApplication is a gigantic no-no. Most compilers perform static initialization before main() is even invoked, so this is a really bad idea. Depending on the class, you'll either crash immediately or run into some super obscure memory allocation/initialization issues down the road that will be bitches to track down.

A QString, like in this scenario, is a perfect example. It's a simple string class? What the hell could possibly ever hurt initializing it statically? The QString class uses a custom allocator to share data between two strings that are equal. So two QStrings holding the same text point to the same region in memory. This mechanism isn't even initialized until you instantiate QApplication... It's well-documented, but I had to find that shit out the hard way after many designs revolving around static QObjects, like you're doing, haha.

Fortunately, there's a pretty easy ass solution. Just make sure it's not INSTANTIATED until after your QApp/QCoreApp:

Code: Select all

class StaticClass {
private:
    static QString *str1;
    static QString *str2;
public:
    static void StaticConstructor();
};
Then initialize the static QObject POINTERS as such:

Code: Select all

QString *StaticClass::str1 = NULL;
QString *StaticClass::str2 = NULL;
And define yourself a simple little static constructor as:

Code: Select all

void StaticClass::StaticConstructor() {
    str1 = new QString("Text1");
    str2 = new QString("Text2");
}
Now simply call your static constructor from main or your main window constructor AFTER QApp/QCoreApp has been initialized and before you actually use the static QObjects.
User avatar
short
ES Beta Backer
ES Beta Backer
Posts: 548
Joined: Thu Apr 30, 2009 2:22 am
Current Project: c++, c
Favorite Gaming Platforms: SNES, PS2, SNES, SNES, PC NES
Programming Language of Choice: c, c++
Location: Oregon, US

Re: Solution wide code

Post by short »

Whoah you wrote the rover in QT? Haha I figured at most it had a C compiler. That's awesome.
That isn't technically an "initialization" with the assignment operator (only basic data types can be initialized with an assignment in C++). You must provide a constructor for the object with that functionality. Luckily, QT does that:
Lol whoops, thanks I had no idea! Assignment is not "initialization" for non basic data types, got it.
A QString, like in this scenario, is a perfect example. It's a simple string class? What the hell could possibly ever hurt initializing it statically? The QString class uses a custom allocator to share data between two strings that are equal. So two QStrings holding the same text point to the same region in memory. This mechanism isn't even initialized until you instantiate QApplication... It's well-documented, but I had to find that shit out the hard way after many designs revolving around static QObjects, like you're doing, haha.
Makes complete sense, well almost. The following:
Fortunately, there's a pretty easy ass solution. Just make sure it's not INSTANTIATED until after your QApp/QCoreApp:

Code: Select all

    class StaticClass {
    private:
        static QString *str1;
        static QString *str2;
    public:
        static void StaticConstructor();
    };
Then initialize the static QObject POINTERS as such:

Code: Select all

    QString *StaticClass::str1 = NULL;
    QString *StaticClass::str2 = NULL;
And define yourself a simple little static constructor as:

Code: Select all

    void StaticClass::StaticConstructor() {
        str1 = new QString("Text1");
        str2 = new QString("Text2");
    }
Now simply call your static constructor from main or your main window constructor AFTER QApp/QCoreApp has been initialized and before you actually use the static QObjects.
If in my main function I call my newly created static constructor, I can access each string elsewhere in my code via:

Code: Select all

other code...
qDebug() << StaticClass::str1 << endl


That makes sense, and I would assume (no time to confirm) that this way would be faster then the inline function call that happens every time with my method. Thanks! I learned something cool today, c++ static classes are shaky for me.

I do have a question though,
Then initialize the static QObject POINTERS as such:

Code: Select all

    QString *StaticClass::str1 = NULL;
    QString *StaticClass::str2 = NULL;
What is this statements purpose? I'm almost certain that I would do this before the static constructor call in my main (after the QApplication is initialized, of course) but I am unsure why it is needed. str1 and str2 are declared in the class definition, instantiated with the constructor, is it necessary to set them to NULL explicitly?

On another note how does being done with senior design make you feel? I get to show mine off this Friday at our engineering expo, and I feel come Friday a HUGE weight will be off my shoulders. I saw on Facebook awhile back you were working your ass to have yours done on time. I bet your glad its over, I'm curious if you enjoyed yours. I personally have HATED mine. My group-mates didn't do jack shit all year, it kinda brought my motivation down being I was the only one writing code. Literally one of my group members wrote 0 lines of code all year. I'm still debating whether or not to try and fail them. I really liked learning Qt though, I am definitely going to keep using it.
My github repository contains the project I am currently working on,
link: https://github.com/bjadamson
User avatar
Falco Girgis
Elysian Shadows Team
Elysian Shadows Team
Posts: 10294
Joined: Thu May 20, 2004 2:04 pm
Current Project: Elysian Shadows
Favorite Gaming Platforms: Dreamcast, SNES, NES
Programming Language of Choice: C/++
Location: Studio Vorbis, AL
Contact:

Re: Solution wide code

Post by Falco Girgis »

short wrote:Whoah you wrote the rover in QT? Haha I figured at most it had a C compiler. That's awesome.
Haha, naaaah. It wasn't quite that hardcore. It was pretty much a weak-ass PC. It even ran Ubuntu as its OS... hardly embedded. Definitely limited resources, but I did use QT for the software framework running on it.
short wrote:Makes complete sense, well almost. The following:
Fortunately, there's a pretty easy ass solution. Just make sure it's not INSTANTIATED until after your QApp/QCoreApp:

Code: Select all

    class StaticClass {
    private:
        static QString *str1;
        static QString *str2;
    public:
        static void StaticConstructor();
    };
Then initialize the static QObject POINTERS as such:

Code: Select all

    QString *StaticClass::str1 = NULL;
    QString *StaticClass::str2 = NULL;
And define yourself a simple little static constructor as:

Code: Select all

    void StaticClass::StaticConstructor() {
        str1 = new QString("Text1");
        str2 = new QString("Text2");
    }
Now simply call your static constructor from main or your main window constructor AFTER QApp/QCoreApp has been initialized and before you actually use the static QObjects.
If in my main function I call my newly created static constructor, I can access each string elsewhere in my code via:

Code: Select all

other code...
qDebug() << StaticClass::str1 << endl
Yep, 'cept you have to dereference the pointer:

Code: Select all

qDebug() << *StaticClass::str1 << endl;
short wrote:That makes sense, and I would assume (no time to confirm) that this way would be faster then the inline function call that happens every time with my method. Thanks! I learned something cool today, c++ static classes are shaky for me.
Yeah. Since you weren't returning by reference or pointer, it was a copy construct to return by value on the stack like that.
short wrote:I do have a question though,
Then initialize the static QObject POINTERS as such:

Code: Select all

    QString *StaticClass::str1 = NULL;
    QString *StaticClass::str2 = NULL;
What is this statements purpose? I'm almost certain that I would do this before the static constructor call in my main (after the QApplication is initialized, of course) but I am unsure why it is needed. str1 and str2 are declared in the class definition, instantiated with the constructor, is it necessary to set them to NULL explicitly?
Nah, this would actually go in your .cpp file corresponding to the static class, or anywhere else at GLOBAL scope. This is just the way static member variables work. Since they're not associated with any particular class, they're internally allocated as global memory. By doing this in your class:

Code: Select all

class StaticClass {
    static QString *ptr;
};
You have simply declared the variable. There is no memory reserved for it. It's essentially the same thing as declaring an extern global variable or using a forward declaration, since the compiler cannot reserve room for a static in the header file (it would be reallocated in every file including it, and your linker would give you a duplicate symbol error).

So along with "declaring" it in your header file, somewhere in your program, at global scope, you must actually allocate/initialize it. This is a simple allocation:

Code: Select all

QString *StaticClass::ptr;
Which works (internally) the exact same way as declaring a global:

Code: Select all

QString *ptr;
C/++ also allows for the initialization of globals upon construction, so we might as well initialize it to NULL like good little programmers:

Code: Select all

QString *StaticClass::ptr = NULL;
short wrote:On another note how does being done with senior design make you feel? I get to show mine off this Friday at our engineering expo, and I feel come Friday a HUGE weight will be off my shoulders. I saw on Facebook awhile back you were working your ass to have yours done on time. I bet your glad its over, I'm curious if you enjoyed yours. I personally have HATED mine. My group-mates didn't do jack shit all year, it kinda brought my motivation down being I was the only one writing code. Literally one of my group members wrote 0 lines of code all year. I'm still debating whether or not to try and fail them. I really liked learning Qt though, I am definitely going to keep using it.
It feels soooooo fucking good to be done with that shit. I'm in the same boat as you were. I was super stoked to start the project, because we were using the Elysian Shadows Toolkit/Engine for a bunch of things (you'll see it in the dev video), and I had never done anything robotics-related in my life.

I was (just like you) the only person really doing any coding in the team. I had to rely on one team-mate who committed to handling the image-processing algorithms in OpenCV. And it turns out that he wound up fucking all of us over by failing to mention that he never bothered to test his code on the rover before a huge competition (because he knew it wouldn't work).

Our project was pretty impressive (if I do say so myself), and we were one of my teacher's favorites. I tried to push us to enter competitions and expos (that we won) for more publicity... while my uncertain team-mates who were not confident enough in their own abilities or experienced enough to keep up really kind of brought it down. In the end, I got to present my software suite with a rover fully ready to be autonomous... except for wait.... the cameras can't fucking detect a single obstacle or are continually false positive... so autonomy was a complete failure...

I took way too many classes... even a graduate class as an elective. I had to spend so much fucking time on just senior design that my other classes suffered, and the fact that my team-mates were clearly not able to keep up really started to bring me down. The pressure mounted so high that I nearly became depressed by the project at the end of the semester... I will never fucking do that to myself again. In the end, I secured an A+, had something really impressive for my resume, and got both me and Kendall (even though she wasn't in my team, haha) interviews with some pretty nice companies... So I guess it all paid off.

But yeah, that's my emo story of the semester and why you haven't seen AiGD18. I'm definitely going to be showing off the Rover in it, though, since it directly ties into ES, and I spent so much time on it...
User avatar
short
ES Beta Backer
ES Beta Backer
Posts: 548
Joined: Thu Apr 30, 2009 2:22 am
Current Project: c++, c
Favorite Gaming Platforms: SNES, PS2, SNES, SNES, PC NES
Programming Language of Choice: c, c++
Location: Oregon, US

Re: Solution wide code

Post by short »

It feels soooooo fucking good to be done with that shit. I'm in the same boat as you were. I was super stoked to start the project, because we were using the Elysian Shadows Toolkit/Engine for a bunch of things (you'll see it in the dev video), and I had never done anything robotics-related in my life.

I was (just like you) the only person really doing any coding in the team. I had to rely on one team-mate who committed to handling the image-processing algorithms in OpenCV. And it turns out that he wound up fucking all of us over by failing to mention that he never bothered to test his code on the rover before a huge competition (because he knew it wouldn't work).

Our project was pretty impressive (if I do say so myself), and we were one of my teacher's favorites. I tried to push us to enter competitions and expos (that we won) for more publicity... while my uncertain team-mates who were not confident enough in their own abilities or experienced enough to keep up really kind of brought it down. In the end, I got to present my software suite with a rover fully ready to be autonomous... except for wait.... the cameras can't fucking detect a single obstacle or are continually false positive... so autonomy was a complete failure...

I took way too many classes... even a graduate class as an elective. I had to spend so much fucking time on just senior design that my other classes suffered, and the fact that my team-mates were clearly not able to keep up really started to bring me down. The pressure mounted so high that I nearly became depressed by the project at the end of the semester... I will never fucking do that to myself again. In the end, I secured an A+, had something really impressive for my resume, and got both me and Kendall (even though she wasn't in my team, haha) interviews with some pretty nice companies... So I guess it all paid off.

But yeah, that's my emo story of the semester and why you haven't seen AiGD18. I'm definitely going to be showing off the Rover in it, though, since it directly ties into ES, and I spent so much time on it...
Weeeeelll congratulations are definitely in order, but your story reaffirms my theory that senior design is a test on good programmers to learn to deal with ... those who seem to care less. I'm glad it all paid off, seems we have/had similar experiences with our senior projects. It's hard not to care, my group-mates are currently making me kind of depressed. I'll try and remember that it will be over soon, and not depress myself to much because my group-mates don't care.

I'm curious with all the C/++ you enjoy, do you care what your new jobs have you do? I currently have a job using C# and I'm kind of indifferent towards it. I hope my next job (internships next year) allow me to put all the focused C++ studying I have been doing to use though.

On topic, I took your suggestions and made the following change: (I stole your comment for my code, hope you don't mind)

obfus.h

Code: Select all

#ifndef OBFUS_H
#define OBFUS_H

#include <QString>

class Obfus{
public:
    // declare static variables
    static QString* _videoFilesDirectory;
    static QString* _playPauseButtonTitle;
    static QString* _recordStopButtonTitle;
    static QString* _playButtonTitle;
    static QString* _pauseButtonTitle;
    static QString* _stopButtonTitle;
    static QString* _recordButtonTitle;
    static QString* _menuButtonTitle;
    static QString* _forwardButtonTitle;
    static QString* _backwardsButtonTitle;
    static QString* _cutButtonTitle;
    static QString* _undoButtonTitle;
    static QString* _emptyButtonTitle;
public:
    /// Static Initializer
    static void StaticConstructor();

    /// Static class methods
    // returns the complete image path for the button name.
    static inline const QString ConstructImagePath(const QString& filename){
	return QString(":/resources/images/" + filename + ".png").toLower();
    }

    // strip the directory path from the filename
    static inline const QString StripVideoDirectoryPathFromFilename(const QString& filename){
	QString t = filename;
	return t.remove(0, _videoFilesDirectory->length());
    }

    static inline const QString& VideoFilesDirectory(){
	return *_videoFilesDirectory;
    }

    static inline const QString& PlayPauseButtonTitle(){
	return *_playPauseButtonTitle;
    }

    static inline const QString& RecordStopButtonTitle(){
	return *_recordStopButtonTitle;
    }

    static inline const QString& PlayButtonTitle(){
	return *_playButtonTitle;
    }

    static inline const QString& PauseButtonTitle(){
	return *_pauseButtonTitle;
    }

    static inline const QString& StopButtonTitle(){
	return *_stopButtonTitle;
    }

    static inline const QString& RecordButtonTitle(){
	return *_recordButtonTitle;
    }

    static inline const QString& MenuButtonTitle(){
	return *_menuButtonTitle;
    }

    static inline const QString& ForwardButtonTitle(){
	return *_forwardButtonTitle;
    }

    static inline const QString& BackwardsButtonTitle(){
	return *_backwardsButtonTitle;
    }

    static inline const QString& CutButtonTitle(){
	return *_cutButtonTitle;
    }

    static inline const QString& UndoButtonTitle(){
	return *_undoButtonTitle;
    }

    static inline const QString& EmptyButtonTitle(){
	return *_emptyButtonTitle;
    }

    /// Public Enumeration
    enum InstanceType {VideoPlayer, VideoEditor, VideoRecorder};

private:
    // do not allow constructor initialization
    Obfus();
    Obfus(const Obfus& ref);
};

#endif // OBFUS_H
Obfus.cpp

Code: Select all

// allocate memory for static variables in GLOBAL memory space (all static variables are in global space)
// C/++ also allows for the initialization of globals upon construction, set to NULL
QString* Obfus::_videoFilesDirectory = NULL;
QString* Obfus::_playPauseButtonTitle = NULL;
QString* Obfus::_recordStopButtonTitle = NULL;
QString* Obfus::_playButtonTitle = NULL;
QString* Obfus::_pauseButtonTitle = NULL;
QString* Obfus::_stopButtonTitle = NULL;
QString* Obfus::_recordButtonTitle = NULL;
QString* Obfus::_menuButtonTitle = NULL;
QString* Obfus::_forwardButtonTitle = NULL;
QString* Obfus::_backwardsButtonTitle = NULL;
QString* Obfus::_cutButtonTitle = NULL;
QString* Obfus::_undoButtonTitle = NULL;
QString* Obfus::_emptyButtonTitle = NULL;

void Obfus::StaticConstructor() {
#ifdef _WIN32
    _videoFilesDirectory = new QString("../video/");
#else
    _videoFilesDirectory = new QString("/home/user/MyDocs/.videos/");
#endif

    _playPauseButtonTitle = new QString("play_pause");
    _recordStopButtonTitle = new QString("record_stop");
    _playButtonTitle = new QString("play");
    _pauseButtonTitle = new QString("pause");
    _stopButtonTitle = new QString("stop");
    _recordButtonTitle = new QString("record");
    _menuButtonTitle = new QString("menu");
    _forwardButtonTitle = new QString("forward");
    _backwardsButtonTitle = new QString("backwards");
    _cutButtonTitle = new QString("cut");
    _undoButtonTitle = new QString("undo");
    _emptyButtonTitle = new QString("empty");
}
I didn't want to have my group mates remember to always de-reference every-time so I made a getter function to return a const reference, which shouldn't incur any extra overhead. I think the design is a little better this way, thanks :)
interviews with some pretty nice companies...
what type of companies? game development?
My github repository contains the project I am currently working on,
link: https://github.com/bjadamson
Post Reply