CC++Qt « C++ private constructor

Так уж случилось, что мне, java-программисту понадобилось написать кое-какое приложение на C++. В качестве среды выбрал VS2008 (все вроде так хвалят ее). Приложение для Windows. Сразу скажу что VS далеко не такая уж удобная, по сравнению с той-же Eclipse (ни тебе красивого подчеркивания ошибок в реальном времени, ни тебе нормального и удобного рефакторинга и т.д.) Вобщем вопрос:
в java я писал так:
/** * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann * (http://qbnz.com/highlighter/ and http://geshi.org/) */ .java.geshi_code {font-family:monospace;} .java.geshi_code .imp {font-weight: bold; color: red;} .java.geshi_code .kw1 {color: #000000; font-weight: bold;} .java.geshi_code .kw2 {color: #000066; font-weight: bold;} .java.geshi_code .kw3 {color: #003399;} .java.geshi_code .kw4 {color: #000066; font-weight: bold;} .java.geshi_code .co1 {color: #666666; font-style: italic;} .java.geshi_code .co2 {color: #006699;} .java.geshi_code .co3 {color: #008000; font-style: italic; font-weight: bold;} .java.geshi_code .coMULTI {color: #666666; font-style: italic;} .java.geshi_code .es0 {color: #000099; font-weight: bold;} .java.geshi_code .br0 {color: #009900;} .java.geshi_code .sy0 {color: #339933;} .java.geshi_code .st0 {color: #0000ff;} .java.geshi_code .nu0 {color: #cc66cc;} .java.geshi_code .me1 {color: #006633;} .java.geshi_code .me2 {color: #006633;} .java.geshi_code span.xtra { display:block; }

public class CounterFactory {
 private static int count = 0;
 
 private CounterFactory() {}

 public static CounterFactory getInstance() {
  count ++;
  return new CounterFactory();
 }
}
 


т.е конструктор приватный, однако вызываю я его из класса. А с++ приватный конструктор, описанный в .h я вызываю из cpp, на что он ругается.. А как вы работаете с приватными конструкторами?

вот код -
/** * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann * (http://qbnz.com/highlighter/ and http://geshi.org/) */ .cpp.geshi_code {font-family:monospace;} .cpp.geshi_code .imp {font-weight: bold; color: red;} .cpp.geshi_code .kw1 {color: #0000ff;} .cpp.geshi_code .kw2 {color: #0000ff;} .cpp.geshi_code .kw3 {color: #0000dd;} .cpp.geshi_code .kw4 {color: #0000ff;} .cpp.geshi_code .co1 {color: #666666;} .cpp.geshi_code .co2 {color: #339900;} .cpp.geshi_code .coMULTI {color: #ff0000; font-style: italic;} .cpp.geshi_code .es0 {color: #000099; font-weight: bold;} .cpp.geshi_code .es1 {color: #000099; font-weight: bold;} .cpp.geshi_code .es2 {color: #660099; font-weight: bold;} .cpp.geshi_code .es3 {color: #660099; font-weight: bold;} .cpp.geshi_code .es4 {color: #660099; font-weight: bold;} .cpp.geshi_code .es5 {color: #006699; font-weight: bold;} .cpp.geshi_code .br0 {color: #008000;} .cpp.geshi_code .sy0 {color: #008000;} .cpp.geshi_code .sy1 {color: #000080;} .cpp.geshi_code .sy2 {color: #000040;} .cpp.geshi_code .sy3 {color: #000040;} .cpp.geshi_code .sy4 {color: #008080;} .cpp.geshi_code .st0 {color: #FF0000;} .cpp.geshi_code .nu0 {color: #0000dd;} .cpp.geshi_code .nu6 {color: #208080;} .cpp.geshi_code .nu8 {color: #208080;} .cpp.geshi_code .nu12 {color: #208080;} .cpp.geshi_code .nu16 {color:#800080;} .cpp.geshi_code .nu17 {color:#800080;} .cpp.geshi_code .nu18 {color:#800080;} .cpp.geshi_code .nu19 {color:#800080;} .cpp.geshi_code .me1 {color: #007788;} .cpp.geshi_code .me2 {color: #007788;} .cpp.geshi_code span.xtra { display:block; }

#ifndef LOGGER_H
#define LOGGER_H

#include <string>
#include <map>

namespace qwe { namespace util {    //namespace qwe::util

class Logger {  
  public:
    typedef Logger* LoggerPtr;

    static LoggerPtr getLogger(const std::string& _logger);
    void info(const std::string& _msg);
    void severe(const std::string& _msg);
    void fine(const std::string& _msg);
    void warning(const std::string& _msg);  

  protected:
  private:
    Logger(const std::string& _name) { loggerName = _name; }
    ~Logger();

    std::string loggerName;
    static std::map<std::string, LoggerPtr> loggers;
 
};
}} // end namespace

#endif

# Logger.cpp --------------------------

#include "../Defines.h" // грабли
#include "Logger.h"

#include <string>
#include <iostream>
#include <map>

using namespace qwe::util;

std::map<std::string, Logger::LoggerPtr> Logger::loggers;

Logger::LoggerPtr Logger::getLogger(const std::string& _logger) {
  Logger::LoggerPtr logger = null;

  if (loggers[_logger] == null) {
    logger = new Logger(_logger);
    loggers[_logger] = logger;    
  } else {
    logger = loggers[_logger];
  }

  return logger;
}

void Logger::fine(const std::string &_msg) {
  std::cout << loggerName << " [FINE]: " << _msg << std::endl;
}

void Logger::info(const std::string &_msg) {
  std::cout << loggerName << " [INFO]: " << _msg << std::endl;
}

void Logger::warning(const std::string &_msg) {
  std::cout << loggerName << " [WARNING]: " << _msg << std::endl;
}

void Logger::severe(const std::string &_msg) {
  std::cout << loggerName << " [SEVERE]: " << _msg << std::endl;
}

 

1 ответов


Попробовал скомпилировать код на VS2008 - все прекрасно работает. Ниже код с незначительными изменениями:

Logger.h


#ifndef LOGGER_H
#define LOGGER_H

#include <string>
#include <map>

namespace qwe { namespace util {    //namespace qwe::util

  class Logger {  
  public:
    typedef Logger* LoggerPtr;

    static LoggerPtr getLogger(const std::string& _logger);
    void info(const std::string& _msg);
    void severe(const std::string& _msg);
    void fine(const std::string& _msg);
    void warning(const std::string& _msg);  

  protected:
  private:
    Logger(const std::string& _name) { loggerName = _name; }
    ~Logger();

    std::string loggerName;
    static std::map<std::string, LoggerPtr> loggers;

  };
}} // end namespace

#endif
 
Logger.cpp

#include "stdafx.h"

#include "logger.h"

#include <string>
#include <iostream>
#include <map>

#define null 0

using namespace qwe::util;

std::map<std::string, Logger::LoggerPtr> Logger::loggers;

Logger::LoggerPtr Logger::getLogger(const std::string& _logger) {
  Logger::LoggerPtr logger = null;

  if (loggers[_logger] == null) {
    logger = new Logger(_logger);
    loggers[_logger] = logger;    
  } else {
    logger = loggers[_logger];
  }

  return logger;
}

void Logger::fine(const std::string &_msg) {
  std::cout << loggerName << " [FINE]: " << _msg << std::endl;
}

void Logger::info(const std::string &_msg) {
  std::cout << loggerName << " [INFO]: " << _msg << std::endl;
}

void Logger::warning(const std::string &_msg) {
  std::cout << loggerName << " [WARNING]: " << _msg << std::endl;
}

void Logger::severe(const std::string &_msg) {
  std::cout << loggerName << " [SEVERE]: " << _msg << std::endl;
}
 
main.cpp

// main.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "logger.h"

using namespace qwe::util;

int _tmain(int argc, _TCHAR* argv[])
{
  Logger::LoggerPtr log = Logger::getLogger("test");
  return 0;
}
 
stdafx.h

// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//

#pragma once

#include "targetver.h"

#include <stdio.h>
#include <tchar.h>



// TODO: reference additional headers your program requires here

 
Отличия:
В файле Logger.cpp убрано подключение Defines.h, добавлен макрос #define null 0, добавлено подключение stdafx.h, т.к. создал проект с предкомпилируемыми заголовочными файлами.

Возможно, проблема в файле Defines.h.

При вызове приватного конструктора из статичного метода класса ошибок не возникает. Посмотрите реализацию любого синглтона с "ленивым" вычислением там используется такой же прием.


А можно было бы увидеть твой с++ код? Кстати VS 2008 хвалят её только потому что нету нормальных аналогов и большинство контор использует её. Если хочешь рефакторить и увидеть подчёркивание/выделение и т.д. запиши себе Visual Assist X для студии =)


Точно так же скомпилировал кусок вашего кода, всё отлично работает, скорей всего проблема не в данном куске кода. К тому же, это типичный метод для создания тех же синглтонов. Как уже сказали выше, проверьте "окружение" вашего кода.

Одно замечание, у вас деструктор тоже приватный, но не видно ни единого метода, который призван освобождать память.


Насколько известно мне, нельзя объявлять конструктор приватным и статичным. Деструктор - можно(касательно приватности). А с конструктором не так. Если, опять же, я не ошибаюсь это объясняется например тем, что когда создаешь объект класса, зачастую надо передавать параметр конструктору, в таком случае как должен на это реагировать компилятор? Если отправит ваш параметр - то конструктор перестанет быть приватным, а если нет, то остается выход - игнорировать, что на мой взгляд достойно ошибки, а не варнинга.