-1

Answers in Initializing private static members say that the private static member should be initialized in the source file.

Hence, this is what I tried:

.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QApplication>

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <iostream>
#include <QDebug>

class MainWindow : public QMainWindow
{
    Q_OBJECT

    static pthread_mutex_t mutexVariable;
    static pthread_cond_t  conditionVariable;
    static QList <int> queueLIFO;

public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();

    static void *producerThreadFunction (void *arg);
    static void *consumerThreadFunction (void *arg);
    int start ();
};

#endif // MAINWINDOW_H

and .cpp

#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    MainWindow::mutexVariable     = PTHREAD_MUTEX_INITIALIZER;
    MainWindow::conditionVariable = PTHREAD_COND_INITIALIZER;
}

error: undefined reference to `MainWindow::mutexVariable'

error: undefined reference to `MainWindow::conditionVariable'


I also tried this:

#include "mainwindow.h"

MainWindow::mutexVariable     = PTHREAD_MUTEX_INITIALIZER;
MainWindow::conditionVariable = PTHREAD_COND_INITIALIZER;


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
}

It resulted in:

error: 'pthread_mutex_t MainWindow::mutexVariable' is private static pthread_mutex_t mutexVariable;// = PTHREAD_MUTEX_INITIALIZER; ^

Community
  • 1
  • 1
CoffeeDay
  • 203
  • 1
  • 11

3 Answers3

2

You should initialize it outside the constructor as separate data variables:

pthread_mutex_t MainWindow::mutexVariable     = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t MainWindow::conditionVariable = PTHREAD_COND_INITIALIZER;

EDIT:

You can refer to this post in SO for explanation of static members initialization.

Community
  • 1
  • 1
Alex Lop.
  • 6,810
  • 1
  • 26
  • 45
  • It worked. I want to know WHY does this work. What was wrong with simply writing "MainWindow::mutexVariable = PTHREAD_MUTEX_INITIALIZER;" outside function definitions. – CoffeeDay Dec 14 '15 at 07:46
  • @CoffeeDay when you write `MainWindow::mutexVariable = PTHREAD_MUTEX_INITIALIZER;` the compiler sees it like you are trying to access `MainWindow::mutexVariable` and assign to it a (new) value and this is forbidden since it is a private member. When you write it with the variable type `pthread_mutex_t MainWindow::mutexVariable = PTHREAD_MUTEX_INITIALIZER;`, the compiler sees it as initialization. – Alex Lop. Dec 14 '15 at 07:50
  • and why can't I write "MainWindow::mutexVariable = PTHREAD_MUTEX_INITIALIZER;" inside the function like I did? – CoffeeDay Dec 14 '15 at 07:52
  • @CoffeeDay, you can, but it's just an assignment expression, not a definition. – Danh Dec 14 '15 at 07:53
  • @CoffeeDay You can (I believe... I think the MainWindow:: won't make an issue here since it is the same class) BUT `static` member has to be initialized at the very beginning even when no object of this class exists. So you have to initialize it separately. Then, you definitely can modify it from any function of that class. – Alex Lop. Dec 14 '15 at 07:55
  • See 9.4.2 [N3797](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf)[class.static.data] >The declaration of a static data member in its class definition is not a definition and may be of an incomplete type other than cv-qualified void. The definition for a static data member shall appear in a namespace scope enclosing the member’s class definition. In the definition at namespace scope, the name of the static data member shall be qualified by its class name using the :: operator. The initializer expression in the definition of a static data member is in the scope of its class – Danh Dec 14 '15 at 07:58
  • @CoffeeDay Also see my EDIT in the post with the relevant link. – Alex Lop. Dec 14 '15 at 07:59
2

According to article 9.4.2 N3797 a.k.a. [class‌​.static.data]

The declaration of a static data member in its class definition is not a definition and may be of an incomplete type other than cv-qualified void. The definition for a static data member shall appear in a namespace scope enclosing the member’s class definition. In the definition at namespace scope, the name of the static data member shall be qualified by its class name using the :: operator. The initializer expression in the definition of a static data member is in the scope of its class

You need to put these line of code outside of the constructor

pthread_mutex_t MainWindow::mutexVariable     = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t MainWindow::conditionVariable = PTHREAD_COND_INITIALIZER;

Updated

End of the day, you can change that value later in constructor, of course I don't know why you need to change it:

#include "mainwindow.h"

pthread_mutex_t MainWindow::mutexVariable     = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t MainWindow::conditionVariable = PTHREAD_COND_INITIALIZER;


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    MainWindow::mutexVariable     = /* another mutex */;
    MainWindow::conditionVariable = /* another mutex */;
}

By the way, I suggest you not use raw mutex and conditional variable. I suggest you use std::mutex and std::condition_variable instead, if you have access to C++11 or later. Or you can use QMutex, QWaitCondition, and QReadWriteLock in Qt instead

Danh
  • 5,916
  • 7
  • 30
  • 45
  • Your edited code is not the same at my given code in the answer. You need a type name `pthread_mutex_t` `pthread_cond_t` – Danh Dec 14 '15 at 08:36
  • Yes, I know, but here you said: http://stackoverflow.com/questions/34261861/initializing-private-static-member-in-cpp-gives-me-error-undefined-reference/34262158?noredirect=1#comment56265511_34261946 – CoffeeDay Dec 14 '15 at 08:37
  • Because you asked: **why can't I write "MainWindow::mutexVariable = PTHREAD_MUTEX_INITIALIZER;" inside the function like I did?** – Danh Dec 14 '15 at 08:38
  • yes, and you said that "you can". But the error above shows that I can't unless I add the type `pthread_mutex_t`. – CoffeeDay Dec 14 '15 at 08:41
  • 1
    If you write it outside a function, it must be a declaration or a definition, it must have a type name. I said you can put your original code **inside** function. I didn't tell you to put it outside function. btw, see me updated answer – Danh Dec 14 '15 at 08:45
1

Assignment and initialization are two completely different things, though they often look confusingly similar. You have assignments, not initializations.

But the error messages don't say "uninitialized", they say "undefined". Which means your program is missing definitios.

pthread_mutex_t MainWindow::mutexVariable     = PTHREAD_MUTEX_INITIALIZER;

This is a definition. You know it is because it starts with a type. You must have exactly one of those for each static data member in your entire program, outside of any function. Initialization is tied to definition and will be performed exactly once (if you use the variable).

MainWindow::mutexVariable     = PTHREAD_MUTEX_INITIALIZER;

This is an assignment. It is only legal inside a function. You can have as many of those as you want, and each one may be performed any number of times.

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243